Безопасно ли вызывать методы временного объекта? - PullRequest
8 голосов
/ 31 марта 2009

У меня есть функция, которая должна возвращать символ *. Поскольку мне нужно объединить некоторые строки, я написал следующую строку:

std::string other_text;
// ...
func(("text" + other_text).c_str());

Я знаю, что мог бы избежать вопроса о названии строки, которую я хочу использовать. Я просто хочу воспользоваться возможностью задать более общий вопрос: безопасно ли вызывать методы временных переменных? это соответствует стандарту?

Ответы [ 4 ]

12 голосов
/ 31 марта 2009

Безопасно вызывать методы временных переменных, но небезопасно возвращать символ * временной переменной для последующего использования.

Этот символ * указывает на буфер, который скоро будет освобожден. После освобождения у вас будет указатель на недопустимую область в памяти.

Вместо этого, пожалуйста, верните объект std :: string.

6 голосов
/ 31 марта 2009

Вам разрешено вызывать методы для временных объектов, однако вы должны быть осторожны с временами жизни объекта - в частности, если у вас есть функция, которая возвращает c_str(), вызванную для временного std::string, этот строковый объект будет уничтожен когда функция возвращается.

Ваш код выше страдает от этой проблемы.

4 голосов
/ 31 марта 2009

C-строка, возвращаемая вызовом c_str () для временного, будет действительна до следующего вызова c_str () для временного, что никогда не может произойти. Само временное хранилище находится в конце полного выражения, частью которого он является (оператор return).

Если бы вы возвращали std :: string, все было бы бесполезно, так как конструктор копирования строки был бы вызван при возврате для получения копии. Если вы вернете char *, то все ставки выключены, поскольку возвращаемое вами значение будет утилизировано при выходе из функции. Это не имеет ничего общего с временным, это общая проблема при возврате char * - вместо этого лучше вернуть std :: strings.

1 голос
/ 31 марта 2009

Сгенерированный указатель будет действителен до тех пор, пока временная переменная все еще существует, что обычно до конца выражения. Исключения составляют случаи, когда временный объект используется в инициализаторе (в этом случае он длится до завершения инициализации) или когда он связан со ссылкой. Временный в операторе return функции продолжается до выхода из функции (если он не связан со ссылкой). Как только временная жизнь заканчивается, временная уничтожается. В этом случае это означает, что строковый деструктор запускается, и поэтому память для символов освобождается. Другими словами, как только значение возвращается, оно гарантированно недействительно.

Вы можете передать саму строку обратно, возвращая ее как константную ссылку. Вы можете скопировать .c_str () во вновь выделенную память и передать ее обратно (как указатель или умный указатель). Любой из них будет работать.

Срок службы временных файлов описан в разделе 12.2 стандарта C ++. Согласно стандарту вы возвращаете указатель на освобожденную память.

...