Произойдет ли преобразование lvalue в rvalue?

Стандарт C ++ (4/5) преобразование lvalue-to-rvalue не выполняется для операнда унарного оператора &.

Например:

int x;
int *p = &x;

В приведенном выше случае p являются ли &x оба значения l? или Какой был бы подходящий пример?

Изменить:

Что насчет этого?

int &r = x;

Я уверен, что в этом заявлении не будет преобразования, но я не понимаю, как в этом участвует оператор &?


person user1086635    schedule 13.12.2011    source источник
comment
есть также значение x. Я думаю, что & x - это rvalue в приведенном выше   -  person BЈовић    schedule 13.12.2011
comment
@VJovic: Да, но речь не идет о C ++ 11: P.   -  person user1086635    schedule 13.12.2011
comment
Хорошо, тогда не обращайте внимания на комментарий   -  person BЈовић    schedule 13.12.2011
comment
Во втором примере нет оператора &.   -  person Puppy    schedule 13.12.2011


Ответы (5)


В цитате сказано, что преобразование не применяется к операнду унарного & (в данном случае x). Таким образом, операнд & - это lvalue.

Это отличается, скажем, от унарного оператора +. Если вы напишете +x, то преобразование lvalue-to-rvalue применяется к подвыражению x (с неопределенным поведением в этом случае, поскольку x не был инициализирован).

Неформально «преобразование lvalue-to-rvalue» означает «чтение значения».

Цитата ничего не говорит о результате &, который на самом деле является r-значением. В int *p = &x;:

  • x - это lvalue, относящееся к переменной с таким именем,
  • &x - это rvalue, это часть инициализатора (в частности, выражение-присваивания),
  • p не является ни rvalue, ни lvalue, потому что это не (под) выражение. Это имя определяемой переменной. В грамматике декларатора C ++ это declarator-id (8/4 в стандарте C ++ 03).

int &r = x; вообще не использует & оператор адресации. Символ & в деклараторе - это просто синтаксис, означающий, что r является ссылкой на int, а не адресом r. В грамматике декларатора C ++ он фактически называется ptr-operator.

person Steve Jessop    schedule 13.12.2011

Думайте о lvalue как о месте хранения, а о rvalue как о значении, которое нужно хранить там. Следовательно, *p - это lvalue, а &x - rvalue. Однако & требует lvalue в качестве операнда (x), но result является rvalue, но это не меняет x самого себя.

person Sebastian Dressler    schedule 13.12.2011
comment
Я не голосовал против. как вы думаете, почему &x это rvalue? Два других ответа @Nawaz и @Kerrek, похоже, с вами не согласны. - person user1086635; 13.12.2011
comment
Когда *p хранит адрес, а &x является адресом x, я предполагаю, что это r-значение, поскольку само это значение не имеет адреса и не может быть l-значением. Или я не прав? В цитируемом отрывке C ++ сказано, что я, но тогда это не имеет для меня смысла. - person Sebastian Dressler; 13.12.2011
comment
Думаю, ты прав. Насколько я понял, &x не делает x rvalue, потому что это просто адрес x, который считается rvalue. +1. - person user1086635; 13.12.2011

Стандартная цитата в основном говорит, что операнд, к которому применяется &, не становится rvalue. Остается lvalue.

Фактически, операнд & не может быть rvalue. Это должно быть lvalue, иначе можно будет получить адрес временного объекта, что не разрешено стандартом:

struct A{};

int *addressOfTemporary_int_object = &(int(10)); //error
A *addressOfTemporary_A_object = &A(); //error

Именно потому, что операнд & должен быть lvalue, приведенные выше выражения недопустимы, поскольку подвыражения int(10) и A() являются выражениями rvalue, поскольку они создают временные объекты.

Также обратите внимание, что даже несмотря на то, что подвыражение x в выражении &x является lvalue, результатом применения & к x является rvalue. То есть выражение &x является rvalue и не может появляться справа от оператора присваивания:

&r = whatever; //illegal

Надеюсь, это поможет вам понять цитату.


Что насчет этого?

int &r = x;

Это хорошо. Здесь & делает r ссылку на объект x. & здесь не является оператором и не связан со ссылкой r, а связан с типом. Менее запутанно записать это как:

int&  r = x;

//Or if you use typedef as
typedef int& intref;
intref r = x;
person Nawaz    schedule 13.12.2011
comment
int (10) и A () являются выражениями rvalue, поскольку они создают временные объекты. int(10) не создает временный объект. - person curiousguy; 25.12.2011
comment
@curiousguy: Это так. Конец обсуждения. - person Nawaz; 25.12.2011
comment
@Nawaz Да. На каком языке? - person curiousguy; 25.12.2011
comment
@curiousguy: Цитата с того языка, на котором это не так. - person Nawaz; 25.12.2011
comment
@curiousguy: Это цитаты из языка? Я просил вас процитировать язык. - person Nawaz; 26.12.2011
comment
позвольте нам продолжить обсуждение в чате - person curiousguy; 26.12.2011
comment
@curiousguy: Вы никогда не цитировали спецификацию языка. Вы объясняете то, чего нет в спецификации. - person Nawaz; 18.02.2012
comment
@curiousguy: Если вы что-то заявляете (и в то же время * интеллектуально честны *), вы должны сообщить мне ссылку из спецификации, подтверждающую ваше утверждение. - person Nawaz; 18.02.2012
comment
@curiousguy: это значит, что вы не понимаете, о чем говорите. - person Nawaz; 18.02.2012
comment
@curiousguy: Ради бога, вы не можете дать мне ссылку? - person Nawaz; 18.02.2012
comment
@curiousguy: Раздел слишком большой. Процитируйте утверждения, которые поддерживают вашу позицию, тогда я поверю. - person Nawaz; 18.02.2012
comment
Вы можете дать мне ссылку, в которой говорится, что int rvalue может относиться к временному объекту типа int? - person curiousguy; 18.02.2012
comment
@curiousguy: Если нет временных объектов неклассового типа, то что делает int const & x = 5? А что бы std::cout << &x << std::endl напечатать? - person Nawaz; 18.02.2012

«В операнде» должно относиться к x с правой стороны. То есть подвыражение x в операторе int *p = &x; не является r-значением, а скорее l-значением. Сравните это с int a = b;, где подвыражение b является r-значением (после преобразования).

person Kerrek SB    schedule 13.12.2011

Стандарт C ++ (4/5) преобразование lvalue-to-rvalue не выполняется для операнда унарного оператора &.

Эта цитата только для того, чтобы вас запутать. Другой цели у него нет. ;)

Самая важная цитата (цитируется N3242, поэтому новая терминология имеет prvalue вместо rvalue):

Всякий раз, когда выражение glvalue появляется как операнд оператора, который ожидает prvalue для этого операнда, стандартные преобразования lvalue-to-rvalue (4.1), массива в указатель (4.2) или функции в указатель (4.3) применяется для преобразования выражения в prvalue.

Таким образом, язык можно описать в терминах конструкций, которые ожидают prvalue, и конструкций, которые этого не делают. В частности, оператор & не ожидает prvalue (как раз наоборот), поэтому неявное преобразование lvalue-to-rvalue не требуется и не будет применяться.

Стандартное описание непоследовательно: в нем никогда явно не говорится, что в x += y неявное преобразование lvalue-to-rvalue не применяется к x, предположительно потому, что это чрезвычайно очевидно. Почему авторы сочли необходимым прямо сказать, что для &x, где это так же очевидно, мне непонятно.

Я думаю, что эти упоминания о том, что неявные преобразования не применяются, следует удалить. Стандарт описывает то, что происходит, а не (бесконечно много) вещей, которых не происходит (если только это не вызывает особого удивления).

Неявные преобразования применяются только для корректировки характера выражения в соответствии с ожидаемым контекстом (контекст может быть выражением, оператором, объявлением, ctor-init-list ...).

Что насчет этого?

int &r = x;

Я уверен, что в этом заявлении не будет конверсии,

потому что здесь не требуется никакого неявного преобразования. Неявное преобразование применяется только при необходимости. Ссылочная привязка не ожидает rvalue.

но я не понимаю, как в этом участвует оператор &?

Нет.

person curiousguy    schedule 25.12.2011