Неправильная форма:
int &z = 12;
Правильная форма:
int y;
int &r = y;
Вопрос :
Почему первый код неправильный? В чем " смысл " ошибки в названии?
Неправильная форма:
int &z = 12;
Правильная форма:
int y;
int &r = y;
Вопрос :
Почему первый код неправильный? В чем " смысл " ошибки в названии?
(ostringstream() << "x=" << x).str()
Ответы:
В C ++ 03 3.10 / 1 сказано: «Каждое выражение является либо lvalue, либо rvalue». Важно помнить, что ценность по сравнению с ценностью - это свойство выражений, а не объектов.
Lvalues именуют объекты, которые сохраняются за пределами одного выражения. Так , например, obj
, *ptr
, ptr[index]
и ++x
все lvalues.
Rvalue - это временные значения, которые испаряются в конце полного выражения, в котором они живут («точка с запятой»). Так , например, 1729
, x + y
, std::string("meow")
и x++
все rvalues.
Оператор адреса требует, чтобы его «операнд был lvalue». если бы мы могли взять адрес одного выражения, это выражение было бы lvalue, иначе это rvalue.
&obj; // valid
&12; //invalid
int & = 12;
недействительно, стандарт говорит, что строковый литерал является lvalue, другие литералы - rvalue.
std::string("meow")
конструирует объект типа std::string
и выдает rvalue, которое обозначает этот объект, 1729
не имеет побочных эффектов и дает значение 1729 как значение типа int
.
"Lvalues name objects that persist beyond a single expression."
на 100% правильное утверждение. Напротив, ваш пример (const int &)1
неверен, потому что это НЕ «именованный» объект.
int &z = 12;
С правой стороны временный объект типа int
создается из интегрального литерала 12
, но временный объект не может быть привязан к неконстантной ссылке. Отсюда и ошибка. Это то же самое, что:
int &z = int(12); //still same error
Почему создается временное? Поскольку ссылка должна ссылаться на объект в памяти, и для того, чтобы объект существовал, он должен быть сначала создан. Поскольку объект не имеет имени, это временный объект. У него нет названия. Из этого объяснения стало довольно ясно, почему второй случай хорош.
Временный объект может быть привязан к ссылке const, что означает, что вы можете сделать это:
const int &z = 12; //ok
Для полноты картины я хотел бы добавить, что в C ++ 11 введена ссылка на rvalue, которая может связываться с временным объектом. Итак, в C ++ 11 вы можете написать это:
int && z = 12; //C+11 only
Обратите внимание, что есть &&
intead of &
. Также обратите внимание, что const
это больше не нужно, даже если объект, с которым z
связывается, является временным объектом, созданным из интегрального литерала 12
.
Поскольку в C ++ 11 введена ссылка на rvalue , int&
отныне она называется lvalue-reference .
12
- это константа времени компиляции, которую нельзя изменить в отличие от данных, на которые ссылается int&
. Что вы можете сделать, это
const int& z = 12;
void f( vector<int> const & )
, которая идиоматична для передачи вектора, который не должен быть изменен. Теперь проблема в том, что это f( vector<int>(5) )
было бы неправильно, и пользователю пришлось бы предоставить другую перегрузку, void f( vector<int> v ) { f(v); }
которая является тривиальной.
f( vector<int>(5) )
компилятор создает временный, а затем связывает ссылку с этим временным, и аналогично если было неявное преобразование из 5
напрямую. Это позволяет компилятору генерировать единую подпись для функции и позволяет реализовать функцию одним пользователем. С этого момента аналогичное поведение определяется для остальных случаев использования постоянных ссылок для согласованности.
T const & r = *ptr;
любое последующее использование r
в функции может быть заменено на *ptr
, и r
не обязательно должно существовать во время выполнения) или его, возможно, придется реализовать, сохранив адрес объекта, которому он присваивает псевдоним (рассмотрите возможность сохранения ссылки как члена объекта) - что реализовано как указатель с автоматическим разыменованием.
Это правила языка C ++:
12
), является "rvalue"int &ri = 12;
сформированоВы должны понимать, что это правила C ++. Они просто есть.
Легко изобрести другой язык, скажем C ++ ', с немного другими правилами. В C ++ 'было бы разрешено создать неконстантную ссылку с rvalue. Здесь нет ничего непоследовательного или невозможного.
Но это позволило бы получить некоторый рискованный код, в котором программист мог бы не получить то, что он задумал, и разработчики C ++ справедливо решили избежать этого риска.
Ссылки - это «скрытые указатели» (ненулевые) на вещи, которые могут изменяться (lvalues). Вы не можете определить их как константу. Это должна быть «переменная» вещь.
РЕДАКТИРОВАТЬ::
Я думаю о
int &x = y;
как почти эквивалент
int* __px = &y;
#define x (*__px)
где __px
- новое имя, и #define x
работает только внутри блока, содержащего объявление x
ссылки.
const
:)
const