Looking for info on C++
Ah you decrement cards_in_deck before using it.
Think I'm going in the right direction?
I'm trying to do it in as few lines as possible but its starting to hurt my brain. I think I can get rid of the card1 but not sure how yet.
Spoiler:
Code:
#include "stdafx.h" #include <iostream> #include <string> #include <vector> #include <stdlib.h> #include <time.h> #include <sstream> using namespace std ; string array_card_string[2][52] = {{"Ah", "2h", "3h", "4h", "5h", "6h", "7h", "8h", "9h", "10h", "Jh", "Qh", "Kh", "Ad", "2d", "3d", "4d", "5d", "6d", "7d", "8d", "9d", "10d", "Jd", "Qd", "Kd", "As", "2s", "3s", "4s", "5s", "6s", "7s", "8s", "9s", "10s", "Js", "Qs", "Ks", "Ac", "2c", "3c", "4c", "5c", "6c", "7c", "8c", "9c", "10c", "Jc", "Qc", "Kc"}, {"11", "2", "3", "4", "5", "6", "7", "8", "9", "10", "10", "10", "10", "11", "2", "3", "4", "5", "6", "7", "8", "9", "10", "10", "10", "10", "11", "2", "3", "4", "5", "6", "7", "8", "9", "10", "10", "10", "10", "11", "2", "3", "4", "5", "6", "7", "8", "9", "10", "10", "10", "10",}}; vector<int> card_vector; int string_to_int_converter(string abc); int RNG(int cards_in_deck); void refresh_deck(); int deal_a_card(int cards_in_deck); int main () { srand(unsigned (time(0))); int cards_in_deck = 53; refresh_deck(); int test = 0; do{ int card1 = deal_a_card(cards_in_deck--); int card2 = deal_a_card(cards_in_deck--); cout << endl << "Your hand is " << array_card_string[0][card1] << " " << array_card_string[0][card2] << endl ; cout << "Your hand value is " << ((string_to_int_converter(string (array_card_string[1][card1]))) + (string_to_int_converter(string (array_card_string[1][card2])))) << endl ; cin >> test; } while (test != 0) ; return 0 ; } int RNG(int cards_in_deck) { int random_number = rand() % cards_in_deck ; return random_number; } void refresh_deck() { for (int y = 0 ; y != 52 ; y++) { card_vector.push_back (y); }; } int deal_a_card(int cards_in_deck) { cards_in_deck--; int ticker = 0 ; do { swap (card_vector[0], card_vector[RNG(cards_in_deck)]) ; // shuffles the deck ticker++ ; } while (ticker != cards_in_deck) ; int xyz ; xyz = card_vector.at(0); card_vector.erase (card_vector.begin()); return xyz; } int string_to_int_converter(string abc) { std::string be_converted = abc; int value = atoi(be_converted.c_str()); return value; }
I'm trying to do it in as few lines as possible but its starting to hurt my brain. I think I can get rid of the card1 but not sure how yet.
Each card has 2 properties:
a string name
a numeric value
You are putting the numeric values in strings because that's the type of array you have for the deck. That is bad: it's a number, save it as a number. It's also bad because you have to "know" how to navigate the array to find the value. "knowing stuff" is your enemy. That's dependencies. As the dependencies grow in a program, so does the complexity. It becomes an entropy battle that kills the program in the end.
Keep related things together:
You can still initialize:
a string name
a numeric value
You are putting the numeric values in strings because that's the type of array you have for the deck. That is bad: it's a number, save it as a number. It's also bad because you have to "know" how to navigate the array to find the value. "knowing stuff" is your enemy. That's dependencies. As the dependencies grow in a program, so does the complexity. It becomes an entropy battle that kills the program in the end.
Keep related things together:
Code:
struct Card { string name; int value; };
Code:
Card cards[] = { {"Ah", 11}, {"2h", 2}, ... };
Was trying to do this >.< seemed like a good idea but took me forever to figure out how to get from string to int.
One suggestion. Try to separate data from code in your program design. You don't want to hard code stuff like the card deck. Because that forces you to modify code whenever you want to change inputs/data into the program. Save the card deck in a text file, and write a class that reads that file and creates the relevant objects.
Over generalizing is its own set of problems.
You don't need to re-shuffle the deck every time you deal a card. You can just do it once. You also don't need a vector because you have a fixed number of cards (52), so you can just use a plain array. Try something like this:
Then you can just call shuffle() from main(). (note: untested code)
Code:
struct Deck { int cards[52]; int top; // array index of the top card in the deck }; Deck deck; void refresh_deck() { for(int i = 0; i < 52; i++) deck.cards[i] = i; deck.top = 51; } void shuffle() { refresh_deck(); for (int i = deck.top; i >= 0; i--) { int r = RNG(i + 1); swap(deck.cards[i], deck.cards[r]); } } int deal_a_card() { if(deck.top < 0) // this is an error condition exit(1); // exit the program int card = deck.cards[deck.top]; // get the top card in the deck deck.top--; return card; }
Agree with Chips Ahoy about using structs to represent the cards as being simpler and more intuitive.
Also, since you're probably focused on learning the functional part of C++ at this point and maybe haven't gotten into objects and classes, using structs is a nice entry point to thinking about objects. In C++, a struct is the same thing as a class (with one difference, which you can ignore for now), and a particular instance of that struct (a concrete variable, such as cards[23]) is also an object of data type Card. And each Card object (struct) has a string object data member and an int data member as we specified in our struct declaration.
If you're not clear on how to use them, say you want the value of either Card data member, you access it with the dot operator like
or
.
This might be getting to far ahead for you, but the traditional way to handle this problem would be to use a deck object that contains a collection of card objects, along with basic functions like shuffle and deal. Here's a simple example where we create a Deck struct (really a class, but this might be a little easier to understand) that has a function known as a constructor, along with the functions deal and shuffle, and an array of Card objects. When we create a Deck, the constructor automatically runs and populates the hands array and shuffles the cards. When we call the deal function, the deck first deals from the first element of the array as indicated by the Deck member variable cardIndex, and after each deal that index is incremented. Once we've dealt all the cards in the deck, the deal function reshuffles the deck without our having to worry about it.
It should be a bit easier to work with Deck and Card objects. Some of the syntax might be a bit confusing, let me know.
Also, since you're probably focused on learning the functional part of C++ at this point and maybe haven't gotten into objects and classes, using structs is a nice entry point to thinking about objects. In C++, a struct is the same thing as a class (with one difference, which you can ignore for now), and a particular instance of that struct (a concrete variable, such as cards[23]) is also an object of data type Card. And each Card object (struct) has a string object data member and an int data member as we specified in our struct declaration.
If you're not clear on how to use them, say you want the value of either Card data member, you access it with the dot operator like
Code:
cards[23].name
Code:
cards[23].value
This might be getting to far ahead for you, but the traditional way to handle this problem would be to use a deck object that contains a collection of card objects, along with basic functions like shuffle and deal. Here's a simple example where we create a Deck struct (really a class, but this might be a little easier to understand) that has a function known as a constructor, along with the functions deal and shuffle, and an array of Card objects. When we create a Deck, the constructor automatically runs and populates the hands array and shuffles the cards. When we call the deal function, the deck first deals from the first element of the array as indicated by the Deck member variable cardIndex, and after each deal that index is incremented. Once we've dealt all the cards in the deck, the deal function reshuffles the deck without our having to worry about it.
It should be a bit easier to work with Deck and Card objects. Some of the syntax might be a bit confusing, let me know.
Code:
#include <cstdlib> #include <iostream> #include <string> #include <ctime> #include <vector> using namespace std; const string Suits[] = {"Spades", "Hearts", "Diamonds", "Clubs"}; const string Ranks[] = {"Ace", "2", "3", "4", "5", "6", "7", "8", "9", "Ten", "Jack", "Queen", "King"}; struct Card { int suit; int rank; }; struct Deck { // Constructor function, runs first automatically each time // a Deck object is created. We can use this to populate cards. Deck() { for( int suit = 0; suit < 4; suit++ ) { for( int rank = 0; rank < 13; rank++ ) { int curCard = suit*13 + rank; cards[curCard].suit = suit; cards[curCard].rank = rank; } } shuffle(); } // member functions void shuffle() { cardIndex = 0; for( int pass = 1; pass <= 1000; pass++ ) { int startIndex = rand() % 52; int newIndex = rand() % 52; Card originalCard = cards[startIndex]; cards[startIndex] = cards[newIndex]; cards[newIndex] = originalCard; // You could also use the swap() function from <algorithm> // swap(cards[startIndex], cards[newIndex]); } } Card deal() { // If we're at the end of the deck we reshuffle the deck // and start over at the first card if( cardIndex > 51 ) { cout << "Shuffling...\n"; shuffle(); } return cards[cardIndex++]; } // data members Card cards[52]; int cardIndex; // this keeps track of how many cards we've dealt from the deck }; int main() { srand((unsigned)time(0)); Deck deck; for( int i = 1; i <= 55; i++ ) { Card card = deck.deal(); cout << "You drew the " << Ranks[card.rank] << " of " << Suits[card.suit] << "\n"; } return 0; }
I'm just going to toss this out here: Once you're reasonably comfortable with the language, spending some time with Stroustrup's big book can be very informative. Don't care how long you've been using C++, you can learn stuff from it.
When I read it I was shocked at times at little features I didn't know.
When I read it I was shocked at times at little features I didn't know.
I will look at those codes, thanks. The main problem I was having was trying to figure out how to keep track of dealer and players hand value so I know if/when someone busts etc. Idk why I was using a vector but they are fun. And now I see why people are bothered to make classes, i couldn't figure it out before but holy **** thats amazing.
Great thread, 5*
Okay I gave OOP a shot and I have to say I like it a lot. But I wanted to check up with you guys before I got into the grunt work of actually making the pieces come together.
it runs but one time it told me i got a value that was out of range or something.
Spoiler:
Code:
#include "stdafx.h" #include <iostream> #include <vector> #include <string> #include <stdlib.h> #include <time.h> #include <sstream> using namespace std; class BlackJack{ public: // Public Functions: void SetDeck () ; void ShuffleDeck () ; void GiveCardPlayer () ; void GiveCardDealer () ; void DisplayPlayerHand () ; void DisplayDealerHand () ; int GetPlayerHandValue () ; int GetDealerHandValue () ; void DisplayPlayerHandValue () ; void DisplayDealerHandValue () ; void PurgeVectors() ; void tester() ; private: //private variables vector<string> CardFace ; // Will get poker value of each card pushed into it vector<int> CardValue ; // Will get poker value of each card pushed into it vector<int> CardNumber ; // Will contain #'s 0-51 vector<string> PlayerHand ; // Gets Ah, 7d, 9s, etc pushed into it vector<string> DealerHand ; // Gets Ah, 7d, 9s, etc pushed into it vector<int> PlayerHandValue ; // Gets 11, 7, 9, pushed into it vector<int> DealerHandValue ; // Gets 11, 7, 9, pushed into it //private functions int RNG () ; int GetZeroCard () ; int BotCardReadAndDestory () ; }; int main () { srand(unsigned (time(0))) ; //used for RNG idk where to put it BlackJack Game; Game.SetDeck(); Game.ShuffleDeck(); Game.GiveCardPlayer(); Game.GiveCardPlayer(); Game.GiveCardDealer(); Game.GiveCardDealer(); cout << "Your Hand is " ; Game.DisplayPlayerHand(); cout << " value is " ; Game.DisplayPlayerHandValue() ; cout << "\nDealer hand is " ; Game.DisplayDealerHand () ; cout << " value is " ; Game.DisplayDealerHandValue() ; cout << "\nDealing you another card...\n" ; Game.GiveCardPlayer(); cout << "Your Hand is " ; Game.DisplayPlayerHand(); cout << " value is " ; Game.DisplayPlayerHandValue() ; Game.PurgeVectors() ; char f ; cin >> f; return 0 ; } //Function definitions // this function will.... void BlackJack::SetDeck () { // make a vector with 52 different playing card "faces" string CardFaceArray[52] = {"Ah", "2h", "3h", "4h", "5h", "6h", "7h", "8h", "9h", "10h", "Jh", "Qh", "Kh", "Ad", "2d", "3d", "4d", "5d", "6d", "7d", "8d", "9d", "10d", "Jd", "Qd", "Kd", "As", "2s", "3s", "4s", "5s", "6s", "7s", "8s", "9s", "10s", "Js", "Qs", "Ks", "Ac", "2c", "3c", "4c", "5c", "6c", "7c", "8c", "9c", "10c", "Jc", "Qc", "Kc"}; // make a vector with 52 (10 unique) poker hand values int CardValueArray[52] = {11, 2, 3, 4, 5, 6, 7, 8, 9, 10, 10, 10, 10, 11, 2, 3, 4, 5, 6, 7, 8, 9, 10, 10, 10, 10, 11, 2, 3, 4, 5, 6, 7, 8, 9, 10, 10, 10, 10, 11, 2, 3, 4, 5, 6, 7, 8, 9, 10, 10, 10, 10}; // and make 1 last vector which is n 0-51 that i use as my meta-index for(size_t i = 0; i != 52 ; i++) { CardNumber.push_back(i) ; CardFace.push_back ( CardFaceArray[i] ) ; CardValue.push_back ( CardValueArray[i] ) ; } } // returns a random number between 0 and 51 int BlackJack::RNG () { int x = rand() % 52 ; return x ; } // uses random number to shuffle deck around void BlackJack::ShuffleDeck () { for (int i = 0; i != 52 ; i++) { int x = RNG() ; swap(CardNumber[i], CardNumber[x]) ; } } // this is seperate just in case int BlackJack::GetZeroCard () { int x = CardNumber.at(0) ; return x ; } //gets value of index card at bottom of deck, saves it, the removes that // index card from the deck int BlackJack::BotCardReadAndDestory () { int x = GetZeroCard () ; int z = CardNumber[x] ; CardNumber.erase (CardNumber.begin() ) ; return z ; } //deal card to player, push that cards face into one vector // and value into another void BlackJack::GiveCardPlayer () { int y = BotCardReadAndDestory () ; PlayerHand.push_back ( CardFace[y] ) ; PlayerHandValue.push_back ( CardValue[y] ) ; } //same thing except push into dealers 2 vectors void BlackJack::GiveCardDealer () { int y = BotCardReadAndDestory () ; DealerHand.push_back ( CardFace[y] ) ; DealerHandValue.push_back ( CardValue[y] ) ; } // cout each card in players hand void BlackJack::DisplayPlayerHand () { for(size_t i = 0; i < PlayerHand.size(); i++) cout << PlayerHand[i] << " " ; } // same for dealer void BlackJack::DisplayDealerHand () { for(size_t i = 0; i < DealerHand.size(); i++) cout << DealerHand[i] << " " ; } // get aggregate value of cards in players hand..... int BlackJack::GetPlayerHandValue () { int x = 0 ; for(size_t i = 0; i < PlayerHandValue.size(); i++) x += PlayerHandValue[i] ; return x ; } // etc int BlackJack::GetDealerHandValue () { int x = 0 ; for(size_t i = 0; i < DealerHandValue.size(); i++) x += DealerHandValue[i] ; return x ; } void BlackJack::DisplayPlayerHandValue () { int x = 0 ; for(size_t i = 0; i < PlayerHandValue.size(); i++) x += PlayerHandValue[i] ; cout << x ; } void BlackJack::DisplayDealerHandValue () { int x = 0 ; for(size_t i = 0; i < DealerHandValue.size(); i++) x += DealerHandValue[i] ; cout << x ; } void BlackJack::tester () { for (size_t y = 0 ; y != 52 ; y++) cout << CardNumber[y] << " " << CardFace[y] << " " << CardValue[y] << endl ; } void BlackJack::PurgeVectors() { CardFace.clear(); CardValue.clear(); CardNumber.clear(); PlayerHand.clear(); DealerHand.clear(); PlayerHandValue.clear(); DealerHandValue.clear(); }
it runs but one time it told me i got a value that was out of range or something.
Took a quick look and there are some things you can do. I would declare your CardFaceArray, and CardValue array as static variables in the black jack class and initialise them in your implementation file (or after the class if you are using a single file).
I'd also create hand and deck classes. It's best to keep your class abstraction consistent. If you find a class with functions that don't really belong together, refactor it into smaller classes.
Don't store the hand strings for the hands. Rather, store just the integers and use the integers to generate the hand string when you want to print it.
You have errors in your BotCardReadAndDestory:
- GetZeroCard returns the value of the card at the first index
- Then you save the value of the card at the index of the returned card value
- then you destroy the first card in the array
Also, at() and [] both do the same thing for std::vectors. You might want to consider having a fixed array and keeping an integer that stores the index of the next card and simply incrementing it when you deal a card and resetting when you shuffle.
Make a deal function to contain:
You don't need to purge your vectors. STL vectors automatically manage their own memory. When main() is out of scope, your BlackJack class object is destructed. When it is destructed all the member objects' destructors are also called (if you have a pointer to an item that you created with new or malloc you will have to destruct the object manually). I'd suggest reading up on Constructors and destructors.
Also, you can do this:
instead of this
I'd also create hand and deck classes. It's best to keep your class abstraction consistent. If you find a class with functions that don't really belong together, refactor it into smaller classes.
Don't store the hand strings for the hands. Rather, store just the integers and use the integers to generate the hand string when you want to print it.
You have errors in your BotCardReadAndDestory:
- GetZeroCard returns the value of the card at the first index
- Then you save the value of the card at the index of the returned card value
- then you destroy the first card in the array
Also, at() and [] both do the same thing for std::vectors. You might want to consider having a fixed array and keeping an integer that stores the index of the next card and simply incrementing it when you deal a card and resetting when you shuffle.
Make a deal function to contain:
Code:
Game.ShuffleDeck(); Game.GiveCardPlayer(); Game.GiveCardPlayer(); Game.GiveCardDealer(); Game.GiveCardDealer();
You don't need to purge your vectors. STL vectors automatically manage their own memory. When main() is out of scope, your BlackJack class object is destructed. When it is destructed all the member objects' destructors are also called (if you have a pointer to an item that you created with new or malloc you will have to destruct the object manually). I'd suggest reading up on Constructors and destructors.
Also, you can do this:
Code:
int BlackJack::RNG () { return rand() % 52 ; }
Code:
int BlackJack::RNG () { int x = rand() % 52 ; return x ; }
I never do expressions in the return. When I'm debugging I want to be able to look at the result of the expression without jumping out of the function. So I can "set next statement", etc.
I think you are moving in the right direction, but having it all in one class I think make it more complex than it needs to be. It makes sense as mentioned above, to have for example a Card class, a Cardstack class (that can be either the deck or a hand) and a Player class. And maybe some other things too
Imagine we defined the Deck and Card structs I gave earlier. Each Card object is responsible for one thing, representing a suit and a value (rank). Each Deck object is reponsible for one thing, representing an actual deck and all the functionality that you can correspond with an actual deck of cards, like dealing a card and shuffling the deck. And the way we've chosen to represent the deck, we can keep a single Deck object around for as many games as we like, with as many players as we like, because it always has 52 cards, and reshuffles itself whenever all 52 cards have been dealt.
We then have the idea of a Player, who represents someone sitting at a Blackjack table, who is dealt 2 cards, and can perform actions like betting, hitting/standing/splitting/doubling etc. We can create a very simple Player class to emulate your actions like this:
Code:
const std::string Suits[] = {"s", "h", "d", "c"}; const std::string Ranks[] = {"A", "2", "3", "4", "5", "6", "7", "8", "9", "T", "J", "Q", "K"}; struct Card { ... }; struct Deck { ... }; class Player { public: Player( Deck &d ) // we have to use pass by reference to share the same Deck : deck(d) // reference member variables have to be initialized here { points = 0; hit(); hit(); } string display() { string handStr; for( int i = 0; i < cards.size(); i++ ) handStr += Ranks[cards[i].rank] + Suits[cards[i].suit] + " "; return handStr; } void hit() { // note we're not treating the variable value of an ace here properly Card card = deck.deal(); points += card.rank < 9 ? card.rank + 1 : 10; // ternary ?: operator cards.push_back(card); } int pointCount() { return points; } private: Deck &deck; vector<Card> cards; int points; };
Code:
int main() { srand((unsigned)time(0)); Deck deck; // one deck to share Player playerOne(deck); // we pass each Player object the same deck Player dealer(deck); cout << "Your hand is " << playerOne.display() << "value is " << playerOne.pointCount() << "\n"; cout << "Dealer hand is " << dealer.display() << "value is " << dealer.pointCount() << "\n"; cout << "Dealing you another card...\n"; playerOne.hit(); cout << "Your hand is " << playerOne.display() << "value is " << playerOne.pointCount() << "\n"; return 0; }
The main idea is that the Player class should be as isolated from actual game mechanics as possible, only performing those actions that any abstract player can perform in a game of Blackjack. We can leave that to a new Blackjack class that can do things like instantiate a deck object (that can be used for all subsequent games), run a game with an artibtrary number of players, etc.
It is supposed to be like that its probably just confusing. I am not using a real deck im using a fake deck of n 0 - 51. i know that 0 is Ah which has a value of 11, and 51 = Kc which has a value of 10, etc because my other 2 vectors are in matching order.
Nevermind, the above quoted is wrong, the guy quoted in the above quoted is right, and his suggestion sounds like a good one xD After enough "random" errors I came back and re-read what you said and now I see what you mean.
It's a bit counterintuitive, but you have to do it like this:
Code:
class foo { static const int card[52]; };
Code:
const int foo::card[52] = { 0, 1, 2.....51};
I have a couple more questions xD I know that in C++, (well, it looks like to me) the standard is passing by value where you are sending a copy of x to a function, and you have to use additional steps (pointers, or at least additional keystrokes) to pass by reference. But I've also heard that in Java the standard is the equivalent to C++ pointers. If that's true, why is that? Is Java objectively "better" in that particular aspect?
Second, is heap vs stack a big deal? When / why would you choose stack over heap?
Second, is heap vs stack a big deal? When / why would you choose stack over heap?
I know that in C++, (well, it looks like to me) the standard is passing by value where you are sending a copy of x to a function, and you have to use additional steps (pointers, or at least additional keystrokes) to pass by reference. But I've also heard that in Java the standard is the equivalent to C++ pointers. If that's true, why is that?
By contrast, C++ gives you lots of ways to pass parameters. You can pass both primitives and objects by value, reference, pointer, or in C++11, by rvalue reference. This gives you a lot more fine-grained control over the system, at the expense of being more complex. Although passing by reference isn't much harder than passing by value. ("void myFunction(int& x)" vs "void myFunction(int x)").
Is Java objectively "better" in that particular aspect?
Second, is heap vs stack a big deal? When / why would you choose stack over heap?
In addition, if you do put them on the heap you have to do your own garbage collection
The usual example is something like a base class Shape, with derived classes Circle, Square, Triangle etc. You declare the function Shape.draw() to be virtual, and have a bunch of pointers of type Shape pointing to various derived objects, like so:
Shape s; // base object
Shape *shapePtr = &s; // base pointer to base object
shapePtr->draw(); // calls Shape::draw()
Triangle t; // derived object
shapePtr = &t; // base pointer to derived object
shapePtr->draw(); // calls Triangle::draw()
Circle c; // another derived object
shapePtr = &c; // base pointer to another derived object
shapePtr->draw() // calls Circle::draw()
We can have a collection of Shape pointers to circles, squares and triangles and C++ can call the right function at run-time.
EDIT: rofl, ignore that. These are still stack objects we're pointing to. Pointers don't have to point to dynamic memory! But usually with polymorphism you'll be dealing with objects passed between scopes, in which case they'd need to be heap objects. So maybe I'm not entirely off-point...
How can this statement be falsified?
I have a couple more questions xD I know that in C++, (well, it looks like to me) the standard is passing by value where you are sending a copy of x to a function, and you have to use additional steps (pointers, or at least additional keystrokes) to pass by reference. But I've also heard that in Java the standard is the equivalent to C++ pointers. If that's true, why is that? Is Java objectively "better" in that particular aspect?
Second, is heap vs stack a big deal? When / why would you choose stack over heap?
Second, is heap vs stack a big deal? When / why would you choose stack over heap?
Object o;
o = new Object();
Line 1 creates a reference variable of type Object. A reference variable is like a pointer in C++. It typically requires 4 bytes (or 8 bytes on 64-bit systems) since it just holds an address. o is also stored on the stack.
Line 2 creates the actual object and saves its memory location in the variable o. The object is created on the heap.
When o goes out of scope the variable (created on the stack) is destroyed. However the actual Object is not destroyed until the Java garbage collector cleans it up (it realizes that no reference variables point to the object, so it is deleted).
In C++ you achieve the same thing with the notation
Object* o;
o = new Object(); // created on heap in c++
The main difference is that when o goes out of scope the created object is not automatically deleted. You must explicitly call the delete operator
delete o; // now object is deleted from heap
In C++ you can also create objects on the stack (this is not possible in Java). You simply use the notation:
Object o; // actually calls the default constructor for Object in C++, object created on stack
Java eliminated these alternative options for simplicity and other design considerations. C++ was designed for performance and flexibility.
Accessing heap objects is generally slower than accessing stack objects. However the stack is much smaller so you don't want to create giant arrays of objects on the stack (in C++).
In C++, the default is to pass by value:
In the above example, the values of x and y don't get changed because they were passed by value, so swap() was operating on copies of their values. If you want swap() to work, you have to pass by reference:
In that example, copies of x and y aren't made; a and b are just references to x and y. Now, pointers are also passed by value:
As you can see, the pointers x and y didn't get swapped. They were passed by value. Copies of the pointers x and y were made and passed to swap(). Note: no copies of m and n, the data that the pointers point to, are made. In order to get swap() to work, you have to do this:
So in Java, object references are equivalent to C++ pointers. And they are always passed by value, as the pointers are in my third C++ example. So hopefully now you understand what I mean when I say that in Java, references are passed by value.
Code:
void swap(int a, int b) { int temp = a; a = b; b = temp; } int main() { int x = 5; int y = 9; swap(x, y); cout << x << endl; // prints "5" cout << y << endl; // prints "9" }
Code:
void swap(int& a, int& b) { int temp = a; a = b; b = temp; } int main() { int x = 5; int y = 9; swap(x, y); cout << x << endl; // prints "9: cout << y << endl; // prints "5" }
Code:
void swap(int* a, int* b) { int* temp = a; a = b; b = temp; } int main() { int m = 5; int n = 9; int* x = &m; // x is a pointer holding the memory address of m int* y = &n; // y holds the address of n cout << *x << endl; // prints "5" cout << *y << endl; // prints "9" swap(x, y); cout << *x << endl; // still prints "5" cout << *y << endl; // still prints "9" }
Code:
void swap(int*& a, int*& b) // note the difference here { int* temp = a; a = b; b = temp; } int main() { int m = 5; int n = 9; int* x = &m; // x is a pointer holding the memory address of m int* y = &n; // y holds the address of n cout << *x << endl; // prints "5" cout << *y << endl; // prints "9" swap(x, y); cout << *x << endl; // now prints "9" cout << *y << endl; // now prints "5" }
Feedback is used for internal purposes. LEARN MORE