Является член rvalue структуры rvalue или lvalue?

Вы можете посмотреть Seam (см. в этой статье для обсуждения использования Seam с JSF и AJAX).

Когда я использовал Судя по всему, в последний раз это было довольно медленно. Возможно, вы захотите создать свой собственный компонент JSF, который генерирует JavaScript (например, используя jQuery, как описано в в этой статье ).

26
задан GManNickG 8 February 2010 в 08:12
поделиться

6 ответов

Членом выражения rvalue является значение rvalue.

Стандарт заявляет в 5.3.5 [expr.ref]:

Если объявлено, что E2 имеет тип «ссылка на T», то E1.E2 является lvalue [...] - Если E2 является нестатическим членом данных, а тип E1 - «cq1 vq1 X», а тип E2 - «cq2 vq2 T», выражение обозначает именованный член объекта, обозначенный первым выражением. Если E1 является lvalue, то E1.E2 является lvalue.

13
ответ дан David Rodríguez - dribeas 28 November 2019 в 17:26
поделиться

Это хорошее время, чтобы узнать, что такое xvalues ​​ и glvalues ​​.

R-значения могут быть двух типов - , значения и , значения . В соответствии с новым стандартом C ++ 17

prvalue - это выражение, вычисление которого инициализирует объект, битовое поле или операнд оператора, как указано в контексте в котором оно появляется.

, поэтому что-то вроде fun() в вашем примере оценивается как prvalue (который является r-значением). Это также говорит нам, что fun().v не является prvalue, так как это не ванильная инициализация.

X-значения , которые также являются r-значениями, определяются так

xvalue (значение «eXpiring») также относится к объекту обычно ближе к концу срока службы (например, ресурсы можно переместить). Определенные виды выражений, включающие ссылки на rvalue (8.3.2), дают значения xvalue. [Пример: Результатом вызова функции, возвращаемый тип которой является rvalue-ссылкой на тип объекта, является xvalue (5.2.2). - конец примера]

В дополнение к rvalues, еще одной зонтичной категорией значений является glvalue , которые бывают двух типов xvalues ​​ и традиционные lvalues .

На данный момент мы определили категории основных значений. Это может быть визуализировано следующим образом

enter image description here

Категория glvalue может широко означать, что lvalues должны были означать до того, как семантика перемещения стала вещью - вещью, которая может быть в левой части выражения. glvalue означает обобщенное lvalue.

Если мы посмотрим на определение значения xvalue , то оно говорит, что что-то является значением xvalue , если оно подходит к концу своего времени жизни. В вашем примере, fun().v подходит к концу своего времени жизни. Таким образом, его ресурсы могут быть перемещены. И поскольку его ресурсы можно перемещать, это не lvalue, поэтому ваше выражение вписывается в единственную оставшуюся категорию значений листьев - xvalue .

2
ответ дан Curious 28 November 2019 в 17:26
поделиться

Это становится очевидным, если учесть, что компилятор сгенерирует для вас конструктор по умолчанию, конструктор копирования по умолчанию и оператор назначения копирования по умолчанию, если ваша структура / класс не содержит ссылочных членов. Затем подумайте, что стандарт позволяет вам вызывать методы-члены для временных переменных, то есть вы можете вызывать неконстантные члены для неконстантных временных.

См. Этот пример:

struct Foo {};
Foo foo () {
    return Foo();
}

struct Bar {
private:
    Bar& operator = (Bar const &); // forbid
};
Bar bar () {
    return Bar();
}
int main () {
    foo() = Foo(); // okay, called operator=() on non-const temporarie
    bar() = Bar(); // error, Bar::operator= is private
}

Если вы напишите

struct Foo {};
const Foo foo () { // return a const value
    return Foo();
}

int main () {
    foo() = Foo(); // error
}

т.е. если вы позволите функции foo () вернуть const временно, тогда произойдет ошибка компиляции.

Чтобы завершить пример, вот как вызывается член const temporarie:

struct Foo {
    int bar () const { return 0xFEED; }
    int frob ()      { return 0xFEED; }
};
const Foo foo () {
    return Foo();
}

int main () {
    foo().bar(); // okay, called const member method
    foo().frob(); // error, called non-const member of const temporary
}

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

Редактировать: И вот необходимые ссылки:

12.2 Временные объекты:

  • 3) [...] Временные объекты уничтожаются как последний шаг в оценке полного выражения (1.9), которое (лексически) содержит точку, где они были созданы. [...]

, а затем (или лучше, раньше)

3.10 L-значения и значения:

  • 10) Lvalue для объекта необходимо для того, чтобы изменить объект, за исключением того, что rvalue типа class также может использоваться для изменения его референта при определенных обстоятельствах. [Пример: функция-член, вызываемая для объекта (9.3), может модифицировать объект. ]

И пример использования: http://en.wikibooks.org/wiki/More_C%2B%2B_Idioms/Named_Parameter

0
ответ дан Sebastian Mach 28 November 2019 в 17:26
поделиться

Я заметил, что в gcc, как правило, очень мало вычислений по поводу использования rvalue в качестве lvalue в выражениях присваивания. Это, например, прекрасно компилируется:

class A {
};

extern A f();

void g()
{
   A myA;
   f() = myA;
}

Почему это законно, а это нет (то есть не компилируется), хотя меня действительно смущает:

extern int f();

void g()
{
   f() = 5;
}

ИМХО, стандартный комитет может кое-что объяснить в отношении lvalues , rvalues ​​и где их можно использовать. Это одна из причин, почему меня так интересует этот вопрос о rvalue .

0
ответ дан 28 November 2019 в 17:26
поделиться

В вашем коде нет сцены. Возвращенная структура размещается в стеке, поэтому результат присваивания будет немедленно потерян.

Ваша функция должна eiter выделить новый экземпляр A следующим образом:

new A()

В этом случае лучшая подпись

A* f(){ ...

Или вернуть существующий экземпляр, например:

static A globalInstance;
A& f(){ 
  return globalInstance;
}
-2
ответ дан 28 November 2019 в 17:26
поделиться

Edit: Ok, кажется, у меня наконец-то есть что-то из стандарта:

Обратите внимание, что v имеет тип int, который имеет встроенный оператор присваивания:

13.3.1.2 Операторы в выражениях

4 Для встроенных операторов присваивания преобразования левого операнда ограничены следующим образом: - не вводятся временные элементы для хранения левого операнда, и [...]

fun1() должен возвращать ссылку. Возвращаемый тип функции, не являющийся ссылкой/указателем, является r-значением.

3.10 L-значения и r-значения

5 Результатом вызова функции, которая не возвращает ссылку на l-значение, является r-значение [...]

Таким образом, fun1().v является r-значением.

8.3.2 Ссылки

2 Ссылочный тип, объявленный с использованием & называется ссылкой lvalue, а ссылочный тип, объявленный с использованием && называется rvalue ссылкой. Ссылки lvalue и rvalue references - это разные типы.

2
ответ дан 28 November 2019 в 17:26
поделиться
Другие вопросы по тегам:

Похожие вопросы: