Разрешают ли ссылки rvalue висячие ссылки? - PullRequest
30 голосов
/ 15 сентября 2010

Рассмотрим ниже.

#include <string>
using std::string;

string middle_name () {
    return "Jaan";
}

int main ()
{
    string&& danger = middle_name();   // ?!
    return 0;
}

Это ничего не вычисляет, но компилируется без ошибок и демонстрирует что-то, что я нахожу запутанным: danger - это свисающая ссылка, не так ли?

Ответы [ 3 ]

41 голосов
/ 15 сентября 2010

Разрешают ли ссылки rvalue висячие ссылки?

Если вы имели в виду «Можно ли создать висячие ссылки rvalue», тогда ответ - да.Ваш пример, однако,

string middle_name () {
    return "Jaan";
}

int main()
{
    string&& nodanger = middle_name();   // OK.
    // The life-time of the temporary is extended
    // to the life-time of the reference.
    return 0;
}

совершенно в порядке.Здесь применяется то же правило, что делает этот пример (статья Херба Саттера) также безопасным.Если вы инициализируете ссылку с pure rvalue , время жизни временного объекта увеличивается до времени жизни ссылки.Тем не менее, вы все еще можете создавать висячие ссылки.Например, это больше не безопасно:

int main()
{
    string&& danger = std::move(middle_name());  // dangling reference !
    return 0;
}

Поскольку std::move возвращает string&& (то есть не a pure rvalue ) правило, которое продлевает срок службы временного, не применяется.Здесь std::move возвращает так называемое xvalue . xvalue - это просто неназванная ссылка на rvalue.Как таковой, он может ссылаться на что угодно, и в принципе невозможно угадать, на что ссылается возвращаемая ссылка, не глядя на реализацию функции.

15 голосов
/ 15 сентября 2010

rvalue ссылки связывают с rvalue. Значение r может быть либо prvalue , либо xvalue [ объяснение ]. Привязка к первому никогда не создает висячих ссылок, привязка ко второму могуществу. Вот почему обычно плохой идеей является выбор T&& в качестве возвращаемого типа функции. std::move является исключением из этого правила.

T&  lvalue();
T   prvalue();
T&& xvalue();

T&& does_not_compile = lvalue();
T&& well_behaved = prvalue();
T&& problematic = xvalue();
3 голосов
/ 15 сентября 2010

danger - это свисающая ссылка, не так ли?

Не более, чем если бы вы использовали const &: danger вступает во владение rvalue.

...