Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How does vector work while pushing back a reference of its element to itself?

Tags:

c++

I first declare a vector of string called test. Then I push_back string Hello and World and let a be a reference of test[0].And then I push_back a into test. However , I printed a before and after push_back respectively and observed that a became nothing after pushed into test. Why a becomes nothing? How does the vector work while pushing back a reference (a) of its element to itself ? Does that mean a is no longer a reference of test[0] ?
Thanks .

Remarks: If I push_back test[0] , a also becomes nothing. But test[0] is still "Hello".

#include <iostream>
#include <string>
#include <vector>
using namespace std;
int main()
{
     vector<string> test;
     test.push_back("Hello");
     test.push_back("World");
     string& a = test[0];
     cout << "1"<< a << "\n";
     test.push_back(a);          //or : test.push_back(test[0]);
     cout << "2"<< a << "\n"; 
} 

Live Demo

output:

1Hello
2

Update:

I got it ,thanks to answers and comments below. I printed the size and capacity of test and observed that they are both 2 . When test.push_back(a)is performed , the vector test allocates new memory and copy its old elements to the new memory . Thus a , the reference of it old elements , become undefined.

Here is the similar code using reserve . I think the reason why a becomes undefined is same as my original question. (Let me know if I'm wrong.)

#include <iostream>
#include <string>
#include <vector>
using namespace std;
int main()
{
     vector<string> test;
     test.push_back("Hello");
     test.push_back("World");
     string& a = test[0];
     cout << "1"<< a << "\n";
     cout << "size:" << test.size() << " capacity:" <<test.capacity() <<"\n";  
     test.reserve(3);       
     cout << "2"<< a << "\n"; 
} 

output:

1Hello
size:2 capacity:2
2
like image 817
Wei-Chia Chen Avatar asked Sep 14 '25 16:09

Wei-Chia Chen


2 Answers

test.push_back(a);          //or : test.push_back(test[0]);

Adds a copy of a as the last element of test. The fact that a is a reference to an element in test is not relevant at all.

After that call, a could be dangling reference. Using it as you have in the line

 cout << "2"<< a << "\n"; 

is cause for undefined behavior.

test[0], on the other hand, returns a reference to the first element of test. It could be a reference to a different object than what a references.

like image 161
R Sahu Avatar answered Sep 16 '25 06:09

R Sahu


The string& a became undefined due to vector::push_back invalidating existing references to the container, per the std::vector definition. See http://en.cppreference.com/w/cpp/container/vector/push_back.

If the new size() is greater than capacity() then all iterators and references (including the past-the-end iterator) are invalidated. Otherwise only the past-the-end iterator is invalidated.

Since you don't know what the capacity of the vector before pushing a was, you can't be sure that your reference wasn't invalidated; this is undefined behavior that may "work" in some cases, but can do anything in others.

like image 36
mkal Avatar answered Sep 16 '25 05:09

mkal