Делает ссылку-член класса продлить жизнь временную?


почему это:

#include <string>
#include <iostream>
using namespace std;

class Sandbox
{
public:
    Sandbox(const string& n) : member(n) {}
    const string& member;
};

int main()
{
    Sandbox sandbox(string("four"));
    cout << "The answer is: " << sandbox.member << endl;
    return 0;
}

дать выход:

ответ:

вместо:

ответ: четыре!--2-->

5 136

5 ответов:

только localconst ссылки продлевают срок службы.

стандарт определяет такое поведение в §8.5.3 / 5, [dcl.в этом.ref], раздел об инициализаторах ссылочных объявлений. Ссылка в вашем примере привязана к аргументу конструктора n, и становится недействительным, когда объект n обязательно выходит из области видимости.

продление срока службы не является транзитивным через аргумент функции. §12.2/5 [класс.временно]:

второй контекст-это когда ссылка привязана к временной. Временное, к которому привязана ссылка, или временное, которое является полным объектом для подобъекта, к которому привязана временная ссылка, сохраняется в течение всего срока действия ссылки, за исключением случаев, указанных ниже. Временная привязка к ссылочному члену в ctor-инициализаторе конструктора (§12.6.2 [class.основа.init]) сохраняется до завершения работы конструктора. Временная привязка к ссылке параметр в вызове функции (§5.2.2 [expr.вызов]) сохраняется до завершения полного выражения, содержащего вызов.

вот самый простой способ объяснить, что произошло:

в main () вы создали строку и передали ее в конструктор. Этот экземпляр строки существовал только в конструкторе. Внутри конструктора вы назначили член для указания непосредственно на этот экземпляр. Когда область покинула конструктор, экземпляр string был уничтожен, а член затем указал на объект string, который больше не существовал. Имея Песочницу.член указывает на ссылку вне его области не будет содержать эти внешние экземпляры в области видимости.

Если вы хотите исправить свою программу для отображения желаемого поведения, внесите следующие изменения:

int main()
{
    string temp = string("four");    
    Sandbox sandbox(temp);
    cout << sandbox.member << endl;
    return 0;
}

теперь темп будет переходить из области видимости в конце функции main (), а не в конце конструктора. Однако, это плохая практика. Переменная-член никогда не должна быть ссылкой на переменную, которая существует вне экземпляра. На практике, вы никогда не знаете, когда эта переменная выйдет из области видимости.

Что Я рекомендуется определить песочницу.член как const string member; это скопирует данные временного параметра в переменную-член вместо назначения переменной-члена в качестве самого временного параметра.

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

  • The cout << "The answer is: " немного будет излучать "The answer is: " на буфер от stdout.

  • тут << sandbox.member бит будет поставлять висячую ссылку в operator << (ostream &, const std::string &), который ссылается неопределенное поведение.

из-за этого, ничего не гарантировано случаться. Программа может работать, казалось бы, нормально или может произойти сбой даже без промывки stdout-это означает, что текст "ответ:" не появится на вашем экране.

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

в целом, вы никогда не должны сохранять ссылки в долгосрочной перспективе. Ссылки хороши для аргументов или локальных переменных, но не для членов класса.

простой ответ : Вы имеете в виду то, что исчез. Следующее будет работать

#include <string>
#include <iostream>
using namespace std;

class Sandbox
{

public:
    const string member = " ";
    Sandbox(const string& n) : member(n) {}//a copy is made

};

int main()
{
    Sandbox sandbox(string("four"));
    cout << "The answer is: " << sandbox.member << endl;
    return 0;
}