2

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.

2
  • 3
    Read the doc on push_back, particularly the part about : "If the new size() is greater than capacity() then all iterators and references (including the past-the-end iterator) are invalidated." Commented May 24, 2015 at 16:41
  • 1
    If you don't want your references to be invalidated, reserve space in advance, e.g. strs.reserve(16); // reserve space for 16 elements. Commented May 24, 2015 at 16:47

2 Answers 2

8

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 vectors 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.

Sign up to request clarification or add additional context in comments.

Comments

1
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'

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.