Object's container field is empty after move and erase

66 views Asked by At

I have two vectors and I want to move an object from one to the other, before I move it I make a pointer to the object. But when I erase the index in first vector then the container within the object is empty if I access it through the pointer. It's difficult to describe, some code will explain it better:

Word.h

class Word
{
public:
    Word(string text);
    ~Word();

    string text;
};

Card.h

class Card
{
public: 
    Card(vector<Word>& words);
    ~Card();

    vector<Word> words;
};

main()

vector<Word> words {
    Word("dog"),
    Word("cat"),
    Word("horse")
};

Card card(words);

vector<Card> deck1;
vector<Card> deck2;

deck1.push_back(move(card));

Card* p = &deck1[0];
deck2.push_back(move(deck1[0]));
cout << p->words.size() << endl; // 3

deck1.erase(deck1.begin());

cout << p->words.size() << endl; // 0 <-- Why is size() 0 here?

p = &deck2[0];
cout << deck2[0].words.size() << endl; // 3 <-- and 3 here
cout << p->words.size() << endl; // <-- and 3 here! 

getchar();
1

There are 1 answers

1
juanchopanza On BEST ANSWER

The moves have no effect because Card has no move constructor or move assignment operator. The vectors deck1 and deck2 contain copies of whatever is pushed into them.

But the problem (or at least, one problem) is that you invalidate p when you erase from deck1. De-referencing p is undefined behaviour (UB).

deck1.push_back(move(card));
Card* p = &deck1[0];
....
deck1.erase(deck1.begin()); // p invalidated
....
cout << p->words.size() << endl; // UB, anything can happen

p = &deck2[0];
cout << deck2[0].words.size() << endl;
cout << p->words.size() << endl; // No problem, p points to deck2[0]