std::string::c_str() и временные

Правильно ли сформирован следующий код C++:

void consumer(char const* p)
{
  std::printf("%s", p);
}

std::string random_string_generator()
{
  // returns a random std::string object
}

consumer(random_string_generator().c_str());

У меня проблема в том, что после создания временного объекта std::string и получения указателя c_str() ничто не препятствует уничтожению объекта std::string (или, может быть, я ошибаюсь?). Не могли бы вы указать мне стандарт, если код в порядке, несмотря ни на что. Это работает, когда я тестирую g++.


person user1095108    schedule 04.04.2012    source источник


Ответы (3)


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

Время жизни временных объектов строго определено, начиная с C++98. До этого он менялся в зависимости от компилятора, и код, который вы написали, не работал бы с g++ (до 1995 года примерно g++ изменил это почти сразу после того, как за него проголосовал комитет по стандартам). (Тогда тоже не было std::string, но те же проблемы затрагивают любой написанный пользователем строковый класс.)

person James Kanze    schedule 04.04.2012
comment
что, если использовать c_str() const char* в последующем операторе (все еще внутри функции, но вне первого оператора)? Принесет ли это нам висячий указатель? - person Alex Gidan; 20.02.2019
comment
Отвечаю сам себе... В этом случае было бы неверным: § 12.2... Временные объекты уничтожаются как последний шаг в вычислении полного выражения (1.9), которое (лексически) содержит точку, где они были созданы . Это справедливо даже в том случае, если эта оценка заканчивается созданием исключения. - person Alex Gidan; 20.02.2019
comment
std::string temp = random_string_generator().c_str(); Правильно ли предположить, что температура будет правильной? так как время жизни строки, возвращаемой из random_string_generator(), будет до конца выражения? - person Ayush Pant; 17.06.2021

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

person Jon    schedule 04.04.2012
comment
Не могли бы вы дать подсказку относительно стандарта С++ 03 или С++ 11, пожалуйста? - person user1095108; 04.04.2012
comment
Срок службы временного объекта определен в §12.2. (Раздел 12 озаглавлен «Специальные функции-члены», и это не совсем то место, где вы ожидаете искать время жизни временных объектов, но оно есть.) - person James Kanze; 04.04.2012
comment
@ user1095108 и время жизни аргументов функции можно получить из §3.2.2 и §3.7.2 стандарта С++ 03. - person juanchopanza; 04.04.2012

Временное значение, возвращаемое функцией random_string_generator(), можно безопасно использовать в функции Consumer().

person dgulabs    schedule 04.04.2012