Подтвердить что ты не робот

Безопасно ли использовать (str1 + str2).c_str()?

Я протестировал этот код:

#include <iostream>
#include <cstdio>
#include <string>
using namespace std;

int main()
{
    string s1("a"),s2("b");
    const char * s = (s1+s2).c_str();
    printf("%s\n",s);
}

Он возвращает "ab".

Насколько я знаю, поскольку (s1 +s2) является временным объектом и может каким-то образом исчезать (я об этом не знаю), тогда const char * s может указывать на память undefined и может быть сброшен.

Так безопасно ли использовать .c_str()?

4b9b3361

Ответ 1

Это небезопасно в вашем примере. Это безопасно, однако, в

printf("%s\n", (a + b).c_str());

Причина в том, что временные значения (например, результат a + b) уничтожаются в конце полного выражения. В вашем примере const char * сохраняется полное выражение, содержащее временное и разыменоваемое поведение undefined.

Худшая часть поведения undefined заключается в том, что все может, по-видимому, работать... (код UB падает только в том случае, если вы делаете свою демонстрацию перед огромной аудиторией, в которую входят ваши родители;-))

Ответ 2

В этом примере мы можем просто указать стандарт:

12.2 Временные объекты [class.temporary]

Временные объекты уничтожаются как последний шаг при оценке полного выражения (1.9), который (лексически) содержит точку, в которой они были созданы. Это справедливо, даже если эта оценка заканчивается выбросом исключения. Вычисления значений и побочные эффекты уничтожения временного объекта связаны только с полным выражением, а не с каким-либо конкретным подвыражением.

Это после точки с запятой вашей строки:

const char * s = (s1+s2).c_str(); // <- Here

Итак, здесь:

printf("%s\n",s); // This line will now cause undefined behaviour.

Почему? Поскольку, поскольку ваш объект разрушен, вы уже не знаете, что сейчас находится в этом месте...

Плохо, что при работе с Undefined ваша программа может работать впервые, но... В худшем случае она будет аварийно завершена...

Вы можете сделать:

printf( "%s\n", (s1+s2).c_str() );

Он будет работать, потому что объект еще не разрушен (помните, после точки с запятой...).

Ответ 3

Это не безопасно, но вы можете легко назначить новую переменную, и указатель будет безопасен в области этой переменной:

string s1("a"), s2("b") , s3;
s3 = s1 + s2;
printf("%s\n", s3.c_str());

//other operations with s3

Ответ 4

Как и большинство программных конструкций, он "безопасен", если вы используете его правильно, и он не "безопасен", если вы неаккуратно. В этом случае правильное использование означает обращать внимание на время жизни объекта. Оператор + создает временный объект, который уничтожается в конце инструкции, а возвращаемый const char* больше не действует после оператора, который его создал. Таким образом, вы можете передать результат c_str() непосредственно функции, но вы не можете сохранить указатель и использовать его позже.