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

Когда временные значения параметров выходят за рамки?

Возможный дубликат:
Время жизни во времени

int LegacyFunction(const char *s) {
    // do something with s, like print it to standard output
    // this function does NOT retain any pointer to s after it returns.
    return strlen(s);
}

std::string ModernFunction() {
    // do something that returns a string
    return "Hello";
}

LegacyFunction(ModernFunction().c_str());

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

  • Существует временный объект строки, который существует после возврата функции ModernFunction. Когда это выходит за рамки?
  • Возможно ли, чтобы компилятор вызывал c_str(), уничтожал этот временный объект строки, а затем передал висячий указатель на LegacyFunction? (Помните, что строковый объект управляет памятью, в которой значение c_str() возвращает значение...)
  • Если приведенный выше код небезопасен, почему он небезопасен, и есть ли лучший, не менее краткий способ его записи, чем добавление временной переменной при выполнении вызовов функций? Если это безопасно, почему?
4b9b3361

Ответ 1

LegacyFunction(ModernFunction().c_str());

Уничтожение копии будет после оценки full expression (т.е. после возврата из LegacyFunction).

n3337 12,2/3

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

n3337 1,9/10

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

struct S {
S(int i): I(i) { }
int& v() { return I; }
private:
int I;
};
S s1(1); // full-expression is call of S::S(int)
S s2 = 2; // full-expression is call of S::S(int)
void f() {
if (S(3).v()) // full-expression includes lvalue-to-rvalue and
// int to bool conversions, performed before
// temporary is deleted at end of full-expression
{ }
}

Ответ 2

Существует временный объект строки, который существует после возврата функции ModernFunction. Когда это выходит за рамки?

Строго говоря, это никогда не имеет границ. Область действия - это свойство имени, а не объекта. Так получилось, что автоматические переменные имеют очень тесную связь между областью действия и временем жизни. Объекты, которые не являются автоматическими переменными, различны.

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

Возможно ли, чтобы компилятор вызывал c_str(), уничтожал этот временный объект строки, а затем передавал оборванный указатель на LegacyFunction

Нет, потому что полное выражение LegacyFunction(ModernFunction().c_str()) (исключая точку с запятой: чувствуйте, что педантизм), поэтому временное значение, которое является возвращаемым значением ModernFunction, не уничтожается до тех пор, пока LegacyFunction не вернется.

Если это безопасно, почему?

Потому что время жизни временного достаточно.

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