Jesse
Jesse

Reputation: 1402

Object's container field is empty after move and erase

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();

Upvotes: 0

Views: 56

Answers (1)

juanchopanza
juanchopanza

Reputation: 227468

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]

Upvotes: 2

Related Questions