Временное и экспрессивное поведение - PullRequest
2 голосов
/ 22 апреля 2011

Это хорошо определенное поведение?

const char* p = (std::string("Hello") + std::string("World")).c_str();
std::cout << p;

Я не уверен.Причины?

Ответы [ 4 ]

6 голосов
/ 22 апреля 2011

Нет, это неопределенное поведение.Временные значения std::string и временные значения, возвращаемые operator+, действуют только до конца инициализации вашего const char* (конец полного выражения).Затем они уничтожаются и p указывает на неопределенную память.

2 голосов
/ 22 апреля 2011

Нет, поведение не определено, потому что p указывает на освобожденное хранилище в std::cout << p;

Временная создается для хранения std::string("Hello") + std::string("World"). Строка в стиле C затем извлекается из этого объекта. В конце выражения временно уничтожается, оставляя p, указывающее на освобожденное хранилище.

Использование p затем вызывает неопределенное поведение.

12.2 / 4 говорит

Есть два контекста, в которых временные уничтожаются в другой точке, чем конец полного выражения. Первый контекст - это когда выражение появляется как инициализатор для декларатора, определяющего объект. В этом контексте временное хранилище, которое содержит результат выражения, должно сохраняться до инициализация завершена.
....

1 голос
/ 22 апреля 2011

он не будет скомпилирован из-за отсутствующей точки с запятой:

const char* p = (std::string("Hello") + std::string("World")).c_str(); //<< important here
std::cout << p;

СЕЙЧАС правило применяется к удалению временного в конце выражения, в котором он используется, то есть в точке с запятой,Таким образом, у вас есть указатель на удаленную память, которая вызывает неопределенное поведение.

0 голосов
/ 22 апреля 2011

Я недавно прочитал эту превосходную книгу http://www.amazon.co.uk/Gotchas-Avoiding-Addison-Wesley-Professional-Computing/dp/0321125185/ref, и если я правильно помню, это в значительной степени один из приведенных там примеров.

Я считаю, что данные, возвращенные из c_str, действительны только до тех пор, пока строковый объект, который их вернул, является действующим. Строковые объекты в вашем примере являются живыми только на время выражения.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...