Член Const Reforment Class Class продлевает срок службы временного?

StackOverflow https://stackoverflow.com/questions/2784262

Вопрос

Почему это:

#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;
}

Дайте вывод:

Ответ:

Вместо:

Ответ: четыре

Это было полезно?

Решение

Только местный const Ссылки продлить срок службы.

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

Расширение пожизненного времени не переходит через аргумент функции. § 12.2 / 5 [Class.temporary]:

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

Другие советы

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

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

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

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

Теперь Temp выйдет из прицела в конце основного (), а не в конце конструктора. Однако это плохая практика. Ваша переменная участника никогда не должна быть ссылки на переменную, которая существует вне экземпляра. На практике вы никогда не знаете, когда эта переменная выйдет из объема.

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

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

  • То cout << "The answer is: " бит будет выделять "The answer is: " в буфер stdout.

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

Из-за этого ничего не гарантировано. Программа может работать, по-видимому, хорошо или может потерпеть краю, даже не промыв STDOUT - означает текст «Ответ:« Не будет отображаться на вашем экране.

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

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

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

#include <string>
#include <iostream>

class Sandbox
{

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

};

int main()
{
    Sandbox sandbox(string("four"));
    std::cout << "The answer is: " << sandbox.member << std::endl;
    return 0;
}
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top