2015-05-24 3 views
2

Поэтому у меня есть следующий код:PRINTF и C++ строки

#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; 
} 

которая довольно проста, но она не работает. printf ничего не печатает. Это печать, если я изменить его на:

const string& a1 = strs[0].c_str(); 

может кто-то пожалуйста объяснить поведение этого.

+3

прочитать документ на [ 'push_back'] (http://en.cppreference.com/w/cpp/ контейнер/вектор/push_back), в частности, часть о: «Если новый' size() 'больше, чем' capacity() ', то все итераторы ** и ссылки ** (включая итератор прошедшего конца) недействительны «. – WhozCraig

+1

Если вы не хотите, чтобы ваши ссылки были недействительными, зарезервируйте место заранее, например. 'Strs.reserve (16); // зарезервируем место для 16 элементов'. – vsoftco

ответ

8

Ваши призывы к push_back потенциально (и в вашем случае, очевидно, фактически) аннулируют все ссылки в vector, а именно, если vector слишком мал для хранения нового элемента. Таким образом, вы не можете использовать ссылки на vector, созданные до push_back, если вы не убедитесь, что емкость vector достаточно велика.

Если вы убедитесь, что vector имеет достаточную емкость для всех элементов (то есть с помощью std::vector::reserve) перед тем создавать ссылки, ваша первая версия будет работать, как ожидалось.

Ваш второй пример работает, потому что вы создаете новый временный string (срок службы которого продлевается до срока службы ссылки), к которому привязывается ссылка.

1
strs.push_back("happy");  
const string& a1 = strs[0]; 

Ваша ссылка действительна до этого момента. Следующий push_back однако создает проблемы

strs.push_back("birthday"); 

Это увеличивает емкость вектора от 1 до 2. Поскольку новая емкость больше, чем старые емкости, все ссылки (а также итераторы), созданных uptill этого момента вектор становится недействительным.

В качестве дополнительной заметки, c_str дает вам символ char * (\ 0 terminated string). Если вставка была в форме

strs.push_back("happ\0y"); 
const string& a1 = strs[0].c_str(); 

a1 будет иметь значение «ГАЭС»

Смежные вопросы