错误:从类型为"int"的右值初始化类型为"int&"的非 const 引用无效
error: invalid initialization of non-const reference of type ‘int&’ from an rvalue of type ‘int’
错误的形式:
int &z = 12;
正确形式:
int y;
int &r = y;
问题:
为什么第一个代码是错误的?标题中错误的">含义"是什么?
C++03 3.10/1说:"每个表达式要么是左值,要么是右值。"重要的是要记住,左值与右值是表达式的属性,而不是对象的属性。
Lvalues命名持久存在于单个表达式之外的对象。例如,obj
、*ptr
、ptr[index]
和++x
都是左值。
R值是临时值,在其所在的完整表达式末尾("在分号处"(蒸发。例如,1729
、x + y
、std::string("meow")
和x++
都是右值。
运算符的地址要求其"操作数应为左值"。如果我们可以取一个表达式的地址,那么这个表达式就是一个左值,否则就是一个右值。
&obj; // valid
&12; //invalid
int &z = 12;
在右侧,类型为int
的临时对象是从整型文字12
创建的,但该临时对象不能绑定到非常量引用。因此出现了错误。与相同
int &z = int(12); //still same error
为什么要创建临时?因为引用必须引用内存中的对象,而要想使对象存在,必须首先创建它。由于该对象未命名,因此它是一个临时对象。它没有名字。从这一解释中,我们可以很清楚地理解为什么第二种情况是好的。
临时对象可以绑定到const引用,这意味着,您可以这样做:
const int &z = 12; //ok
C++11和Rvalue参考:
为了完整起见,我想补充一点,C++11引入了右值引用,它可以绑定到临时对象。所以在C++11中,你可以这样写:
int && z = 12; //C+11 only
注意,&
的后面有&&
。还要注意,const
不再需要,即使z
绑定到的对象是由整数12
创建的临时对象。
由于C++11引入了左值引用,因此int&
现在被称为左值引用。
12
是一个编译时常数,与int&
引用的数据不同,它不能更改。可以做的是
const int& z = 12;
非常量和常量引用绑定遵循不同的规则
以下是C++语言的规则:
- 由文字数字(
12
(组成的表达式是"右值"> - 不允许创建具有右值的常量引用:
int &ri = 12;
格式错误 - 允许使用右值创建const引用:在这种情况下,编译器创建一个未命名的对象;只要引用本身存在,这个对象就会一直存在
你必须明白这些都是C++规则。他们就是这样。
发明一种不同的语言很容易,比如C++,规则略有不同。在C++中,允许创建带有右值的非常量引用。这里没有不一致或不可能的地方。
但它会允许一些有风险的代码,程序员可能无法得到他想要的,C++设计者正确地决定避免这种风险。
引用是指向可以更改的事物(lvalues(的"隐藏指针"(非null(。不能将它们定义为常量。它应该是一个"可变"的东西。
编辑::
我在考虑
int &x = y;
几乎等同于
int* __px = &y;
#define x (*__px)
其中__px
是新名称,而#define x
仅在包含x
引用声明的块内工作。
- 为什么 int 类型的枚举类值不能用作 int
- 如何将文本文件的特定行读取到 int 类型的数组中C++?
- int* 和 int[] 类型对二进制运算符 + 的操作数无效
- 比较两个整数在C++中与未知 int 类型的相等性
- 二进制'operator+' 'int*'和'int*'类型的无效操作数
- 使用元编程选择 int 类型,将生成错误
- 从数组创建 Mat 时,'cv::Mat' 和 'int' 类型不兼容
- 复制初始化 - 从 'int' 类型转换为非标量类型
- 初始化cv :: mat ::具有int类型的定义大小的人
- 处理代码重新定义int类型(uint16_t,int16_t等),并不喜欢它
- 为什么没有"int"类型声明时输出不同?
- 在大型程序中将长变量更改为 int 类型
- 无法将 int 类型转换为时间类型(我的类类型)
- C++:无法在按位函数后将 int 类型设置为非标量
- 无法分配给INT类型的成员[10]
- C++ cin 将字符串读取到 int 类型中返回 0
- 为什么 decltype((i)) 是引用类型,而 decltype(i+0) 是 int 类型
- 使用4用于循环的4矩阵上的数组下标的“ int [int]类型”
- std::is_arithmetic 为通用 lambda 中的 int 类型返回 false:未定义的行为?
- 正在施放带有“ Int”类型的临时性