Reputation: 439
So I have the following code:
#include <iostream>
#include <vector>
#include <string>
using namespace std;
int main() {
vector<string> strs;
strs.push_back("happy");
const string& a1 = strs[0];
strs.push_back("birthday");
const string& a2 = strs[1];
strs.push_back("dude");
const string& a3 = strs[2];
printf("%s\n", a1.c_str());
return 0;
}
which is pretty straightforward but it doesn't work. The printf doesn't print anything. It does print if I change it to:
const string& a1 = strs[0].c_str();
can someone please explain the behavior of it.
Upvotes: 2
Views: 598
Reputation: 1281
strs.push_back("happy");
const string& a1 = strs[0];
Your reference is valid upto this point. The following push_back however creates problems
strs.push_back("birthday");
This increases the capacity of the vector from 1 to 2. Since the new capacity is greater than the old capacity, all references (as well as iterators) created uptill this point on the vector get invalidated.
As a side note, The c_str gives you a char* (\0 terminated string). If your insertion was of the form
strs.push_back("happ\0y");
const string& a1 = strs[0].c_str();
a1 would have the value 'happ'
Upvotes: 1
Reputation: 50053
Your calls to push_back
potentially (and in your case obviously actually) invalidate all references into the vector
, namely if the vector
is too small to store the new element. You thus cannot use any references into the vector
created before a push_back
unless you make sure that the vector
s capacity is big enough.
If you make sure that the vector
has enough capacity for all the elements (i.e. by using std::vector::reserve
) before you create the references, your first version will work as expected.
Your second example works because you create a new, temporary string
(which has its lifetime extended to the lifetime of the reference) the reference binds to.
Upvotes: 8