Почему это:
#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;
}
Дайте вывод:
Ответ:
Вместо того:
Ответ: четыре
c++
temporary
ctor-initializer
const-reference
рукав моря
источник
источник
cout << "The answer is: " << Sandbox(string("four")).member << endl;
, то это гарантированно сработает.SandBox::member
читается, временная строка все еще жива .string("four")
уничтожается в конце полного выражения, а не послеSandbox
выхода из конструктора? В ответе Potatoswatter сказано, что временная привязка к элементу ссылки в ctor-initializer конструктора (§12.6.2 [class.base.init]) сохраняется до выхода из конструктора.Ответы:
Только местные
const
ссылки продлевают срок службы.Стандарт определяет такое поведение в §8.5.3 / 5, [dcl.init.ref], разделе об инициализаторах ссылочных объявлений. Ссылка в вашем примере привязана к аргументу конструктора
n
и становится недействительной, когда объектn
привязан к выходу из области видимости.Увеличение продолжительности жизни не транзитивно через аргумент функции. §12.2 / 5 [класс.время]:
источник
member
он привязан к временному объекту , поскольку инициализацияmember
сn
помощью средства для привязкиmember
к одному и тому же объектуn
привязана, и в данном случае это фактически временный объект.const
кавычка.Вот самый простой способ объяснить, что произошло:
В main () вы создали строку и передали ее в конструктор. Этот экземпляр строки существовал только внутри конструктора. Внутри конструктора вы назначили член, чтобы указывать непосредственно на этот экземпляр. Когда область видимости покинула конструктор, экземпляр строки был уничтожен, а член указал на строковый объект, которого больше не было. Если указатель Sandbox.member на ссылку за пределами его области действия, эти внешние экземпляры не будут удерживаться в области действия.
Если вы хотите исправить свою программу для отображения желаемого поведения, внесите следующие изменения:
Теперь temp будет выходить из области видимости в конце main (), а не в конце конструктора. Однако это плохая практика. Ваша переменная-член никогда не должна быть ссылкой на переменную, которая существует вне экземпляра. На практике вы никогда не знаете, когда эта переменная выйдет из области видимости.
Я рекомендую определить Sandbox.member как a.
const string member;
Это позволит скопировать данные временного параметра в переменную-член вместо назначения переменной-члена в качестве самого временного параметра.источник
const string & temp = string("four"); Sandbox sandbox(temp); cout << sandbox.member << endl;
это все еще будет работать?const string &temp = string("four");
дает тот же результат, что иconst string temp("four");
, если вы не используетеdecltype(temp)
специальноHowever, this is bad practice.
- Зачем? Если и временный объект, и содержащий объект используют автоматическое хранение в одной и той же области, разве это не на 100% безопасно? И если вы этого не сделаете, что бы вы сделали, если строка слишком большая и слишком дорогая для копирования?Технически говоря, эта программа не обязана выводить что-либо на стандартный вывод (для начала это буферный поток).
cout << "The answer is: "
Бит будет излучать"The answer is: "
в буфер на стандартный вывод.Затем
<< sandbox.member
бит будет содержать висячую ссылкуoperator << (ostream &, const std::string &)
, которая вызывает неопределенное поведение .Из-за этого ничего не гарантируется. Программа может работать на первый взгляд нормально или может зависнуть даже без очистки стандартного вывода - это означает, что текст «Ответ:» не появится на вашем экране.
источник
"The answer is: "
будет написано где угодно.Потому что ваша временная строка вышла из области видимости после того, как вернулся конструктор Sandbox, и стек, занятый ею, был освобожден для некоторых других целей.
Как правило, вы никогда не должны сохранять ссылки в долгосрочной перспективе. Ссылки хороши для аргументов или локальных переменных, но не для членов класса.
источник
Вы имеете в виду что-то, что исчезло. Следующее будет работать
источник