C++ constructor takes temporary object not working as expected - c++

For the code below:
struct Test
{
int size;
Test(int a) { cout << "default" << endl; size = a; }
Test(Test const & t) { cout << "copy" << endl; size = t.size + 1; }
Test(Test && t) { cout << "move" << endl; size = t.size + 1; }
~Test() { cout << "destruct" << endl; }
};
struct Test2
{
int size;
Test2(int a) { cout << "default2" << endl; size = a; }
Test2(Test const & t) { cout << "copy2" << endl; size = t.size + 1; }
Test2(Test && t) { cout << "move2" << endl; size = t.size + 1; }
~Test2() { cout << "destruct2" << endl; }
};
I found the result are different as:
Test t{3}; // default
cout << t.size << endl; // 3
Test move_from_temp = Test(Test(std::move(t))); // move
cout << move_from_temp.size << endl; // 4
Test t{3}; // default
cout << t.size << endl; // 3
Test2 move_from_temp = Test2(Test(std::move(t))); // move, move2, destruct
cout << move_from_temp.size << endl; // 5
However, I expect these two should have the same results. Anyone know the reason for this?

If I run your code the result is slightly different (maybe a typo in your Q?)
Test t{3}; // default
cout << t.size << endl; // 3
Test move_from_temp = Test(Test(std::move(t))); // move
cout << move_from_temp.size << endl; // 4
Test t{3}; // default
cout << t.size << endl; // 3
Test2 move_from_temp = Test2(Test(std::move(t))); // move, move2, destruct
cout << move_from_temp.size << endl; // 5
std::move is static_cast to an rvalue reference type. It does nothing, only a cast to Test && in both versions.
Based on that, in both versions you call the move constructur Test(Test&&).
In the first version you are then done because of mandatory "copy elison" https://en.cppreference.com/w/cpp/language/copy_elision
In the second version you call Test2(Test&&) which cannot be optimized away. The compiler just call the method you provided.

Related

Array, avoid pulling Duplicates, simple code, C++

Its a card game, I draw 2 cards from the deck (the array) with the help of two functions.
Each element of the array represent one card with a symbol Spades, Hearts, Diamonds or Clubs.
These numbers in the array \5 \4 \3 \6, represent Clubs, Dimaond, Heatrs, spades (just if ur curious)
The problem!
When I draw a card two times I sometimes get Duplicates.. The same card twice.
How do I make sure the same card cant be drawn twice?
How do I avoid getting duplicates??
This is how the code Looks like.
Some INFO about the array...
The further in, in the array, the higher value the element has.
I have shortened the array... for easy testing of a solution... later the array will be 52 elements.
array<string, 3> cards = { "Ess \5", "Ess \4", "Ess \3" };
//The function.
pair<string, int> draw_card()
{
int random_index = rand() % 52;
string card = cards[random_index];
return { card, random_index };
}
int main()
{
// Seed, random.
srand((unsigned int)time(NULL));
// Calling the function 2 times.
pair<string, int> you_drew = draw_card();
cout << "You drew: " << you_drew.first << endl;
pair<string, int> comp_drew = draw_card();
cout << "Computer drew: " << comp_drew.first << endl;
// Deciding the winner.
int your_score{ 0 };
int the_computers_score{ 0 };
if (you_drew.second > comp_drew.second) {
cout << "You Won!" << endl;
your_score++;
}
else if (you_drew.second < comp_drew.second) {
cout << "You Lost!" << endl;
the_computers_score++;
}
return 0;
}
Everything is working fine, EXCEPT sometimes I get duplicates... I want to make sure I can Not get that...
Somehow when I draw a card the element in the array should not be able to be drawn.. I want to avoid getting duplicates. Please help me!
Shouldnt something like this work? its not but.. shouldnt it?
pair<string, int> comp_drew = draw_card();
if (you_drew == comp_drew) {
bool run8 = true;
while (run8) {
pair<string, int> comp_drew = draw_card();
if (comp_drew != you_drew) {
cout << "Computer drew: " << comp_drew.first << endl;
run8 = false;
}
}
}
Or maybe another solution..
Perhaps after calling the function one time i can delete the return index from the array?
You can swap the drawn card to the end and only choose an index smaller than 51 the next time.
int array_len = 52; // global variables are not great, but it's easier here
pair<string, int> draw_card()
{
int random_index = rand() % array_len;
--array_len;
string card = cards[random_index];
std::swap(cards[random_index], cards[array_len]);
return { card, random_index };
}
There are many different ways to do this.
std::random_shuffle
#include <iostream>
#include <algorithm>
using namespace std;
class CardMachine {
static unsigned constexpr DECK_SIZE = 4;
int cards[DECK_SIZE] = {1,2,3,4};
int lastUsedCardIndex = -1;
public:
int getCard() {
if (lastUsedCardIndex == DECK_SIZE - 1)
shuffle();
return cards[++lastUsedCardIndex];
}
void shuffle() {
random_shuffle(begin(cards), end(cards));
}
};
int main()
{
CardMachine cardMachine = CardMachine();
cout << "unhsuffled - 1,2,3,4 without duplicates:" << endl;
cout << cardMachine.getCard() << endl;
cout << cardMachine.getCard() << endl;
cout << cardMachine.getCard() << endl;
cout << cardMachine.getCard() << endl;
cout << "Shuffled. Random order, and still no duplicates:" << endl;
cardMachine.shuffle(); // or call getCard which can shuffle
cout << cardMachine.getCard() << endl;
cout << cardMachine.getCard() << endl;
cout << cardMachine.getCard() << endl;
cout << cardMachine.getCard() << endl;
return EXIT_SUCCESS;
}
Mark Card as Taken
#include <iostream>
#include <random>
using namespace std;
class CardMachine {
static unsigned constexpr DECK_SIZE = 4;
inline static int constexpr cards[DECK_SIZE] = {1,2,3,4};
bool cardIsGone[DECK_SIZE] = {false, false, false, false};
public:
int getCard() {
while(true) {
int const RANDOM_INDEX = rand()%DECK_SIZE;
if(!cardIsGone[RANDOM_INDEX]) {
cardIsGone[RANDOM_INDEX] = true;
return cards[RANDOM_INDEX];
}
}
}
void shuffle() {
for(bool &isGone : cardIsGone)
isGone = false;
lastUsedCardIndex = -1;
}
};
int main()
{
CardMachine cardMachine = CardMachine();
cout << "Shuffled - Random order, and still no duplicates:" << endl;
cout << cardMachine.getCard() << endl;
cout << cardMachine.getCard() << endl;
cout << cardMachine.getCard() << endl;
cout << cardMachine.getCard() << endl;
cout << "Shuffled. Random order, and still no duplicates:" << endl;
cardMachine.shuffle(); // Causes infinite loop if you call getCard DECK_SIZE + 1 times
cout << cardMachine.getCard() << endl;
cout << cardMachine.getCard() << endl;
cout << cardMachine.getCard() << endl;
cout << cardMachine.getCard() << endl;
return EXIT_SUCCESS;
}
It's not the most efficient solution, but with small values like 52, it should be instant.
Swap Used Cards to Back and Keep Track of Range
#include <iostream>
#include <random>
using namespace std;
class CardMachine {
static unsigned constexpr DECK_SIZE = 4;
int cards[DECK_SIZE] = {1,2,3,4};
int lastCardIndexExlusive = DECK_SIZE;
public:
int getCard() {
int const RANDOM_INDEX = rand()%lastCardIndexExlusive;
swap(cards[RANDOM_INDEX],cards[lastCardIndexExlusive - 1]);
return cards[--lastCardIndexExlusive];
}
void shuffle() {
lastCardIndexExlusive = DECK_SIZE;
}
};
int main()
{
CardMachine cardMachine = CardMachine();
cout << "Shuffled - Random order, and still no duplicates:" << endl;
cout << cardMachine.getCard() << endl;
cout << cardMachine.getCard() << endl;
cout << cardMachine.getCard() << endl;
cout << cardMachine.getCard() << endl;
cout << "Shuffled. Random order, and still no duplicates:" << endl;
cardMachine.shuffle(); // Causes exception if getCard DECK_SIZE + 1 times
cout << cardMachine.getCard() << endl;
cout << cardMachine.getCard() << endl;
cout << cardMachine.getCard() << endl;
cout << cardMachine.getCard() << endl;
return EXIT_SUCCESS;
}
Remember Last Card
#include <iostream>
#include <random>
using namespace std;
class CardMachine {
static unsigned constexpr DECK_SIZE = 4;
int cards[DECK_SIZE] = {1,2,3,4};
int lastCard = -1;
public:
int getCard() {
int const RANDOM_INDEX = rand()%DECK_SIZE;
if (lastCard == RANDOM_INDEX) {
return getCard();
}
lastCard = cards[RANDOM_INDEX];
return lastCard;
}
void shuffle() {
lastCard = -1;
}
};
int main()
{
CardMachine cardMachine = CardMachine();
cout << "Shuffled - Random order, and still no duplicates, but only able to produce 2:" << endl;
cout << cardMachine.getCard() << endl;
cout << cardMachine.getCard() << endl;
cout << "Shuffled. Random order, and still no duplicates:" << endl;
cardMachine.shuffle(); // Causes potential duplicates if getCards 3+ times
cout << cardMachine.getCard() << endl;
cout << cardMachine.getCard() << endl;
return EXIT_SUCCESS;
}
All of these solutions make use of a class to hold state for use in getCard to make sure we get the right behavior.

C++: Why does a member in a derived struct, defined via struct-template, not hide the respective member variable in the base struct?

I am posting my code below as tested, with the respective outputs shown in comments after the "cout"-statements, and my QUESTIONS as to the output that I do not understand indicated by "--> WHY". I am completely at a loss and I apologize in advance for my assumed stupidity that appears to prevent me from understanding what is going on.
#include <experimental/filesystem>
#include <iostream>
#include <vector>
using namespace std;
struct S
{
struct BASE
{
static double testval;
virtual void set_testval(double val) {testval = val;}
virtual double get_testval() {return testval;}
};
template<typename T>
struct DerivedTemplate : public BASE
{
static double testval;
void set_testval(double val) {testval = val;}
double get_testval() {return testval;}
};
struct DERIVED_01 : DerivedTemplate<DERIVED_01>
{
//...
};
struct DERIVED_02 : DerivedTemplate<DERIVED_02>
{
//...
};
struct DERIVED_03 : DerivedTemplate<DERIVED_03>
{
//...
};
vector<unique_ptr<BASE> > DERIVED_TYPES;
S();
}; // END struct S
S::S()
{
DERIVED_TYPES.resize(4);
}
double S::BASE::testval = 0;
template <typename T>
double S::DerivedTemplate<T>::testval = 1;
S s;
int main()
{
// Assign pointers to objects of derived structs to fields in vector of unique_ptr of base struct
{
unique_ptr<S::DERIVED_01> DERIVED (new S::DERIVED_01());
s.DERIVED_TYPES[0] = move(DERIVED);
}
{
unique_ptr<S::DERIVED_02> DERIVED (new S::DERIVED_02());
s.DERIVED_TYPES[1] = move(DERIVED);
}
{
unique_ptr<S::BASE> BASE (new S::BASE());
s.DERIVED_TYPES[2] = move(BASE);
}
{
unique_ptr<S::DERIVED_03> DERIVED (new S::DERIVED_03());
s.DERIVED_TYPES[3] = move(DERIVED);
}
cout << s.DERIVED_TYPES[0]->testval << endl; // Output: 0
cout << s.DERIVED_TYPES[0]->get_testval() << endl; // Output: 1 --> WHY is the output of this line "1" while that of the prior line was "0"?
// I assumed to be accessing the same member variable of the same object in both cases
cout << endl;
cout << s.DERIVED_TYPES[1]->testval << endl; // Output: 0
cout << s.DERIVED_TYPES[1]->get_testval() << endl; // Output: 1 --> WHY [same question]
cout << endl;
cout << s.DERIVED_TYPES[2]->testval << endl; // Output: 0
cout << s.DERIVED_TYPES[2]->get_testval() << endl; // Output: 0
cout << endl;
cout << s.DERIVED_TYPES[3]->testval << endl; // Output: 0
cout << s.DERIVED_TYPES[3]->get_testval() << endl; // Output: 1 --> WHY [same question]
cout << endl;
// Assign values to static member variables of derived struct objects
s.DERIVED_TYPES[0]->testval = 0.5;
s.DERIVED_TYPES[1]->testval = 1.5;
s.DERIVED_TYPES[2]->testval = 2.5;
s.DERIVED_TYPES[3]->testval = 2.75;
cout << s.DERIVED_TYPES[0]->testval << endl; // Output: 2.75
cout << s.DERIVED_TYPES[1]->testval << endl; // Output: 2.75
cout << s.DERIVED_TYPES[2]->testval << endl; // Output: 2.75
cout << s.DERIVED_TYPES[3]->testval << endl; // Output: 2.75 --> WHY are the outputs all "2.75"?
cout << endl;
s.DERIVED_TYPES[0]->set_testval(3.5);
s.DERIVED_TYPES[1]->set_testval(4.5);
s.DERIVED_TYPES[2]->set_testval(5.5);
s.DERIVED_TYPES[3]->set_testval(6.5);
cout << s.DERIVED_TYPES[0]->testval << endl; // Output: 5.5
cout << s.DERIVED_TYPES[0]->get_testval() << endl; // Output: 3.5
cout << endl;
cout << s.DERIVED_TYPES[1]->testval << endl; // Output: 5.5
cout << s.DERIVED_TYPES[1]->get_testval() << endl; // Output: 4.5
cout << endl;
cout << s.DERIVED_TYPES[2]->testval << endl; // Output: 5.5
cout << s.DERIVED_TYPES[2]->get_testval() << endl; // Output: 5.5
cout << endl;
cout << s.DERIVED_TYPES[3]->testval << endl; // Output: 5.5
cout << s.DERIVED_TYPES[3]->get_testval() << endl; // Output: 6.5
// Now, a "DIRECT ACCESS" of "testval" [s.DERIVED_TYPES[x]->testval]
// does not produce an output equal to the value assigned to
// s.DERIVED_TYPES[3]->testval, the last one assigned, but an
// output equal to the one assigned to the pointer pointing to the
// one object of struct BASE instead of "DERIVED_..."
// --> WHY?
cin.get();
return 0;
}

Is passing an r-value to functions returning it considered wrong in C++?

I want to create a function Service that energize an exhausted phone and return it as follows.
Writing
Phone p;
p = Service(p);
does not look elegant so I want to write as follows.
Phone& p = Service(Phone());
Doing so produces weird outputs as follows.
Ctor
Dtor
Destroyed
Energy: 100%
Ending...
The expected output is:
Ctor
Energy: 100%
Dtor
Destroyed
Ending...
Question
Could you tell me why this happens?
Note: I am new to C++.
class Phone
{
private:
int energy;
bool destroyed = false;
public:
Phone() : energy{ 0 } {
cout << "Ctor" << endl;
}
~Phone()
{
cout << "Dtor" << endl;
if (destroyed == false)
{
cout << "Destroyed..." << endl;
destroyed = true;
}
}
void Energize() { energy = 100; }
void Status() const
{
cout << "Energy: " << energy << "%" << endl;
}
};
Phone& Service(Phone&& input)
{
input.Energize();
return input;
}
int main()
{
Phone& p = Service(Phone());
p.Status();
cout << "Ending..." << endl;
}
It makes no sense to return a copy of the phone. So just pass it as reference and operate on it:
void Service(Phone& phone);
Phone p{};
Service(p);

Assigning a vector element to result of function that invokes emplace_back?

The test method on the following class does not have the effect I would expect it to. I have a suspicion it is something to do with the fact that the invocation of emplace_back somehow invalidates the reference obtained via the subscript.
Either way I would expect the second print in test to result in
v[0] = 1
however both result in
v[0] = 5
suggesting that the assignment does not take place.
class FooBar {
vector<size_t> v;
public:
size_t add(size_t x) {
cout << "add(" << x << ")" << endl;
size_t K(v.size());
v.emplace_back(x);
return K;
}
void test(size_t idx) {
cout << "v[" << idx << "] = " << v[idx] << endl;
v[idx] = add(0);
cout << "v[" << idx << "] = " << v[idx]<< endl;
}
};
int main(int argc, char* argv[])
{
FooBar f;
f.add(5);
f.test(0);
}
I know that I can get around the problem by creating a temporary to store the result of add and then perform the assignment but I am interested as to why I cannot use just a straight assignment and why I do not get any kind of error when attempting to perform this.
Compiled and tested with MSVC (Visual Studio 2015).
The line
v[idx] = add(0);
is cause for undefined behavior. You are modifying the contents of v in add while assuming that v[idx] will be valid.
For predictable behavior, you can use:
void test(size_t idx) {
cout << "v[" << idx << "] = " << v[idx] << endl;
size_t val = add(0);
v[idx] = val;
cout << "v[" << idx << "] = " << v[idx]<< endl;
}

how to use exceptions and pointers in a vector class

I have this vector class, and I was provided with a driver to test the class. Most of it seems to work fine but I think there is something wrong with the exceptions part (which I haven't quite fully understood)
Here is the code for the class .cpp file
int myVector::at(int i)
{
if(i<vsize)
return array[i];
throw 10;
}
and here is the driver code
#include "myVector.h"
#include <iostream>
using namespace std;
int main()
{
// Create a default vector (cap = 2)
myVector sam;
// push some data into sam
cout << "\nPushing three values into sam";
sam.push_back(21);
sam.push_back(31);
sam.push_back(41);
cout << "\nThe values in sam are: ";
// test for out of bounds condition here
for (int i = 0; i < sam.size( ) + 1; i++)
{
try
{
cout << sam.at(i) << " ";
}
catch(int badIndex)
{
cout << "\nOut of bounds at index " << badIndex << endl;
}
}
cout << "\n--------------\n";
// clear sam and display its size and capacity
sam.clear( );
cout << "\nsam has been cleared.";
cout << "\nSam's size is now " << sam.size( );
cout << "\nSam's capacity is now " << sam.capacity( ) << endl;
cout << "---------------\n";
// Push 12 values into the vector - it should grow
cout << "\nPush 12 values into sam.";
for (int i = 0; i < 12; i++)
sam.push_back(i);
cout << "\nSam's size is now " << sam.size( );
cout << "\nSam's capcacity is now " << sam.capacity( ) << endl;
cout << "---------------\n";
cout << "\nTest to see if contents are correct...";
// display the values in the vector
for (int i = 0; i < sam.size( ); i++)
{
cout << sam.at(i) << " ";
}
cout << "\n--------------\n";
cout << "\n\nTest Complete...";
cout << endl;
system("PAUSE");
return 0;
}
Any help is appreciated. Thanks
The driver that you have provided:
try {
cout << sam.at(i) << " ";
}
catch(int badIndex) {
cout << "\nOut of bounds at index " << badIndex << endl;
}
expects that int will be thrown (a bit weird design, but well... this is the code that will use your class...). Your implementation of at() might look like this:
int& myVector::at(int i) throw(int) {
if (i < vsize)
return array[i];
throw i;
}
just try to follow one simple rule: throw by value, catch by reference.
Also note that you have a pointer:
private:
int* array;
which points to dynamically allocated memory allocated in constructor and copy constructor and freed in destructor :
myVector::myVector(int i)
{
...
array = new int[maxsize];
}
myVector::myVector(const myVector& v)//copy constructor
{
...
array =new int[maxsize];
}
myVector::~myVector()
{
delete[] array;
}
But how about the assignment operator ? See What is The Rule of Three?
Your stop condition of for loop ends it one element after the last one (i.e. you cannot access 4th element of sam vector because there are only three elements).
std::vector::at throws std::out_of_range exception in such situation (see: http://en.cppreference.com/w/cpp/container/vector/at), not int one. So you should change your exception handling part to something like this:
#include <exception>
try
{
cout << sam.at(i) << " ";
}
catch(std::out_of_range exc)
{
cout << "\nOut of bounds at index " << exc.what() << endl;
}