Является ли ссылка lvalue, возвращаемая функцией, на самом деле rvalue (с точки зрения вызывающей стороны)? - PullRequest
1 голос
/ 15 апреля 2019

Как можно, чтобы ссылка lvalue ссылалась на ссылку lvalue, возвращаемую из функции? Разве ссылка lvalue, возвращаемая из этой функции, на самом деле не является значением r с точки зрения вызывающей стороны? Например:

class Obj {};

Obj& refToRef(Obj& o) {
    return o;
}

int main() {
    Obj o;
    Obj& o2 = refToRef(o);
}

Как o2 (ссылка на lvalue) может ссылаться на то, что выглядит как r-значение?

Ответы [ 2 ]

8 голосов
/ 15 апреля 2019

Разве ссылка lvalue, возвращаемая из этой функции, на самом деле не является значением r с точки зрения вызывающего абонента?

Нет, поскольку результат вызова функции не всегда значение.

с [expr.call] / 14 (выделено мной):

Вызов функции является lvalueесли тип результата является ссылочным типом lvalue или ссылкой rvalue на тип функции, xvalue, если тип результата является ссылкой rvalue на тип объекта, и prvalue в противном случае.

I 'Я уверен, что это правило существует специально для того, чтобы избежать проблемы, о которой спрашивает ваш вопрос.

1 голос
/ 15 апреля 2019

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

  • Lvalue = имеет идентификатор и не может быть перемещен
  • Xvalue = имеет идентификатор и является подвижным
  • Rvalue = не имеет идентификатора и является подвижным

refToRef возвращает по ссылке lvalue, поэтому Obj, на который ссылается refToRef(o),объект с идентификатором (определено &refToRef(o)), и он все еще будет присутствовать после вычисления выражения.Следовательно, refToRef(o) является lvalue.

Кроме того, будьте осторожны, чтобы не перепутать тип со значением.Если я добавлю функцию, которая возвращает значение, и создам из нее ссылку на rvalue, ссылка на rvalue будет lvalue.Например,

class Obj {};
Obj& refToRef(Obj& o) {
    return o;
}

Obj refToVal(Obj& o) {
    return o;
}
int main() {
    Obj o;
    Obj& o2 = refToRef(o);
    Obj&& o3 = refToVal(o);
}

o3 имеет тип rvalue refernce to Obj, а в качестве выражения - lvalue.

...