Время жизни временной переменной C ++ сокращено путем привязки к элементу ссылки? - PullRequest
0 голосов
/ 21 сентября 2018

До этого момента я исходил из предположения, что временный объект уничтожается в конце полного выражения , содержащего его.Недавно я наткнулся на раздел [class.teven] / 5 спецификации, в котором говорится об исключениях, которые возникают, когда временный объект назначается ссылке.По большей части это, кажется, всегда продлевает срок службы временной переменной, за исключением одного особого случая в [class.teven] / 5 :

  • Временная привязка к ссылочному члену в ctor-initializer конструктора (12.6.2) сохраняется до выхода из конструктора.
  • Временная привязка к ссылочному параметру в вызове функции (5.2.2)сохраняется до завершения полного выражения, содержащего вызов.

Если я читаю это, это указывает на то, что срок службы такого объекта может быть короче, чем full-выражение , если конструктор ссылается на него.

Пример:

struct A
{
   A(int);
   ~A();

};

struct B
{
    B(const A& a)
    : memberRef(a)
    { }

    ~B();

    const A& memberRef;
};

// Just a few operators to use in my full expression
int operator+(const A&, const A&);
int operator+(const A&, const B&);

void testCase()
{
   int case1 = A(1) + A(2);
   int case2 = A(3) + B(A(4));
}

Я дал каждому конструктору A свой аргумент, чтобы было легко обращаться к временным переменнымсоздается как A1 , A2 , A3 и BA4 .

В случае 1, A1 и A2 создаются в любом порядке, затем происходит сложение.Продолжительность жизни A1 и A2 регулируется правилами для ссылок на параметры для вызова функции.Они распространяются на полное выражение, содержащее оператор сложения.

Деструкторы должны вызываться в обратном порядке, также в [class.teven] / 5:

Если время жизнииз двух или более временных объектов, ссылки на которые связаны, заканчиваются в одной и той же точке, эти временные объекты уничтожаются в этой точке в обратном порядке завершения их построения.

Так что это говорит мне о том, что деструкторыэти объекты должны быть вызваны в A1 , A2 или A2 , A1 , в зависимости от порядка, который компилятор выбрал для созданияобъекты.Пока все хорошо.

Проблемным делом для меня является case2.Если я прочитал это правильно, потому что A4 привязан к ссылке, переданной в B::B(const A&), его срок жизни теперь заканчивается в конце этого конструктора, , а не в конце выражения .

Это наводит на мысль, что деструкторы могут называться A4 , A3 , BA4 или A4 , BA4 , A3 .Однако деструктор для A4 всегда должен стоять первым, потому что он возникает в конце конструктора для BA4 , а не в конце полного выражения.

Предполагается, что деструкторы не могут быть вызваны в следующем порядке: A3 , BA4 , A4 , поскольку потребности в продолжительности жизни A4 быть сокращенным.

Правильно ли я читаю спецификацию? Если да, то в чем смысл этого правила?Мне кажется более естественным сделать временные переходы, передаваемые конструкторам, живыми, пока временные переходы переходят к вызовам функций, но похоже, что разработчики спецификаций предприняли усилия, чтобы создать правила иначе.

1 Ответ

0 голосов
/ 21 сентября 2018

Вы используете неправильный маркер между двумя.

Этот :

Временная привязка к элементу ссылки в конструкторе ctor-initializer ([class.base.init]) сохраняется до выхода из конструктора.

здесь не применяется.У нас нет временной привязки к ссылочному элементу в ctor-initializer .Эта ситуация была бы больше похожа на:

struct B
{
    B()
    : memberRef(A(2)) // <== 
    { }

    ~B();

    const A& memberRef;
};

Наша ситуация точно эта :

Временная привязка к ссылочному параметру в вызове функции ([expr.call]) сохраняется до завершения полного выражения , содержащий вызов.

Мы имеем временные (A(4)) связанно с опорным параметром вконструктор (вызов конструктора по-прежнему является вызовом функции, параметр, к которому мы привязываем, является a в B(const A& a)), поэтому временный параметр сохраняется до завершения полного выражения .

Другими словами, в том, что вы показали, нет висящих ссылок.Все эти правила, касающиеся привязки временных ссылок к ссылкам, относятся к продолжительности жизни продлению .Никто из них не сокращает продолжительность жизни.

...