Увеличение продолжительности жизни, значения и значения

После хорошо принятого ответа на этот вопрос Допускают ли ссылки на rvalue висячие ссылки? Казалось бы, значения xvalue не продлеваются, когда они присваиваются rvalue-ссылке lvalue, как в вопросе. Однако, когда я делаю это

#include <iostream>

using namespace std;

class Something {
public:
    Something() {
        cout << "Something()" << endl;
    }
    Something(const Something&) {
        cout << "Something(const Something&)" << endl;
    }
    Something(Something&&) {
        cout << "Something(Something&&)" << endl;
    }
    ~Something() {
        cout << "~Something()" << endl;
    }

    int a;
};

Something make_something() {
    return Something{};
}

int main() {
    auto&& something = make_something().a;

    return 0;
}

Время жизни объекта, возвращаемого вызовом make_something продлен, хотя make_something().a является значением xvalue согласно http://en.cppreference.com/w/cpp/language/value_category (в третьем пункте в объяснении xvalues ​​перечислены права доступа к элементу, которые у меня есть выше, в качестве значения xvalue,)

am, член выражения объекта, где a является значением r, а m является нестатическим членом данных не ссылочного типа;

Если категории значений не определяют, когда время жизни значения r будет увеличено, то что тогда? Мне трудно понять, когда время жизни rvalue продлено в C++

2 ответа

Увеличение продолжительности жизни не заботит категории значений. Как сказано в [class.tevent]/p6:

Временный объект, к которому привязана ссылка, или временный объект, являющийся полным объектом подобъекта, к которому привязана ссылка, сохраняется в течение всего времени существования ссылки.

Акцент добавлен.

Здесь ничего не сказано о категории значений выражения, на которое делается ссылка.

То, что определяет, является ли временный объект расширенным, является точно вышеизложенным (и еще несколькими правилами).


Но это не объясняет, почему добавление std::move() вокруг временного, которому назначается ссылка, не продлевает срок службы

std::move не магическая, определяемая компилятором конструкция в C++. Это вызов функции, и поэтому он ведет себя не иначе, как любой другой вызов функции C++.

Итак, если у вас есть std::move(Type()), что это значит? Это значит, что вы создадите временную, привязав ее к параметруstd::move, затем вызовите ту функцию, которая будет что-то возвращать.

Привязка временного к параметру функции, как указано в [class.teditional]/p6, означает, что время жизни временного объекта устанавливается равным времени жизни полного выражения, которое его создало (если не для этого правила, то временное будет должны быть уничтожены в конце вызова функции, так как это конец времени жизни ссылки).

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

Если категории значений не определяют, когда время жизни значения r будет увеличено, то что тогда? Мне трудно понять, когда время жизни rvalue продлено в C++

Обратите внимание, что категории значений описывают выражения, а не объекты. Категории значений (xvalue, prvalue или что-либо еще) не будут расширяться каким-либо образом. Только объекты могут иметь жизнь.

Из стандартного чертежа n4296:

  • §12.2.1

    Временные объекты типа класса создаются в различных контекстах: привязка ссылки к prvalue (8.5.3), возвращение prvalue (6.6.3), преобразование, которое создает prvalue (4.1, 5.2.9, 5.2.11, 5.4), выбрасывая исключение (15.1), и в некоторых инициализациях (8.5).

а также

  • §12.2.4

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

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

Таким образом, категория значения выражения функции makesomething() это prvalue создание временного типа класса, согласно первому абзацу, указанному выше.
makesomething().a доступ к временному, полному подобъекту. Связывание этого временного объекта со ссылкой приводит, согласно второму контексту, указанному выше, к увеличению срока службы.


Время жизни подобъекта a связан со временем жизни предыдущего созданного временного объекта, что делает его значением с истекающим сроком (xvalue). Без продления времени жизни путем привязки его к ссылке он будет уничтожен вместе с временным объектом класса. Таким образом, в этом случае после ;,

Другие вопросы по тегам