Подтвердить что ты не робот

Ссылки rvalue позволяют обманывать ссылки?

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

#include <string>
using std::string;

string middle_name () {
    return "Jaan";
}

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

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

4b9b3361

Ответ 1

Ссылки 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;
}

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

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

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

Ответ 2

Ссылки rvalue привязаны к значениям r. Значение 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

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

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