14.7.3 Временные объекты могут исчезнуть раньше, чем ожидается ¶
Опасно использовать указатели или ссылки на части временного объекта. Компилятор может удалить объект гораздо раньше, чем ожидается, оставив указатель на мусор. Эта проблема чаще всего возникает в классах, подобных строковым классам, особенно в тех, которые определяют функцию преобразования в тип char * или const char * — это одна из причин, почему стандартный string класс требует вызова функции-члена c_str. Однако любая функция, возвращающая указатель на некоторую внутреннюю структуру, потенциально подвержена этой проблеме.
Например, программа может использовать функцию strfunc, которая возвращает объекты string, и другую функцию charfunc, которая работает с указателями на char:
string strfunc ();
void charfunc (const char *);
void
f ()
{
const char *p = strfunc().c_str();
…
charfunc (p);
…
charfunc (p);
}
В этой ситуации может показаться разумным сохранить указатель на строку C, возвращаемую функцией-членом c_str, и использовать его вместо многократного вызова c_str. Однако временная строка, созданная при вызове strfunc, уничтожается после инициализации p, в результате чего p указывает на освобожденную память.
Код подобного вида может работать успешно под другими компиляторами, особенно устаревшими компиляторами на основе cfront, которые удаляют временные переменные вместе с обычными локальными переменными. Однако поведение GNU C++ соответствует стандарту, поэтому, если ваша программа зависит от позднего уничтожения временных объектов, она не будет переносимой.
Безопасный способ написания такого кода — дать временному объекту имя, что заставит его сохраниться до конца области видимости имени. Например:
const string& tmp = strfunc (); charfunc (tmp.c_str ());
© Free Software Foundation
Licensed under the GNU Free Documentation License, Version 1.3.
https://gcc.gnu.org/onlinedocs/gcc-11.4.0/gcc/Temporaries.html