C++ 斯科特·迈尔斯论右旋价值
我观看了这部电影,从中我学到了关于右值引用、移动和转发的大部分知识。有一次,他说的是右值,而不是变量的类型,他说的是“右值独立于类型” 我知道你可以有这样的方法:C++ 斯科特·迈尔斯论右旋价值,c++,c++11,move-semantics,rvalue-reference,C++,C++11,Move Semantics,Rvalue Reference,我观看了这部电影,从中我学到了关于右值引用、移动和转发的大部分知识。有一次,他说的是右值,而不是变量的类型,他说的是“右值独立于类型” 我知道你可以有这样的方法: void func(MyType&& rRef) { // Do domething with rRef... } 这里的rRef是一个左值,因为它可以被识别,它的地址可以被获取,等等,即使它的类型是MyType& 但是右值不能是任何类型,对吗?我的意思是,它只能是一个MyType&&,对吗?从这个意义上说,
void func(MyType&& rRef)
{
// Do domething with rRef...
}
这里的rRef
是一个左值,因为它可以被识别,它的地址可以被获取,等等,即使它的类型是MyType&
但是右值不能是任何类型,对吗?我的意思是,它只能是一个MyType&&
,对吗?从这个意义上说,我认为类型并不完全独立于价值。也许我错过了什么
更新:我的观点可以这样说得更清楚。如果在func()
void gunc(MyType&& rRef)
{
// ...
}
void gunc(MyType& lRef)
{
// ...
}
i、 e.通过调用gunc(std::move(rRef))
或gunc(rRef)
,括号之间的结果表达式的类型似乎与右值无关。我认为您省略了他的部分引用:
最后一点值得记住:左值还是右值
表达式的类型与它的类型无关
他解释道。他的主要观点是:
表达式的类型不会告诉您它是左值还是左值
右旋值
在他的结束语中:
在类型声明中,&&“表示右值引用或
通用引用–可解析为左值或左值的引用
引用或右值引用。普遍引用总是具有相同的含义
对于某些导出的类型T,形式T&&
引用崩溃是导致泛化的机制
引用(在某些情况下实际上只是右值引用)
引用崩溃发生的位置)有时解析为左值
引用,有时是右值引用。它发生在特定的时间
编译过程中可能出现引用的上下文。
这些上下文是模板类型推断、自动类型推断、,
typedef的形成和使用,以及decltype表达式
这里使用类型T
表示任何类型。它可以是int&
,或者double&
,或者Widget&&
——这没关系。首先,让我们将讨论限制在纯右值引用,而将通用引用放在一边。我们不是在谈论模板。。。T&&var…
就常规Type&&var=somevalue代码>右值引用的情况下,我认为其含义如下:
绑定到此引用的内容在绑定到该引用时是“一次性的”。它超出了范围。如果你在装订时修改了它,没有人会知道。在它被绑定时,没有其他引用
这允许我们对右值引用有一些自由,而对其他类型的变量则没有这种自由。想到的第一个用法是使用swap()窃取其内容。表达式的类型没有任何引用的痕迹。因此,如果我们假设引用可以具有引用类型,那么我们将具有以下内容
int a = 0;
int &ra = a;
int c = a + 42;
int d = ra + 42;
在上面,表达式a
将具有类型int
,表达式ra
将具有类型int&
。我认为,在规范中几乎所有与表达式和类型相关的规则中,例如说“表达式E必须是X类型”的规则,我们必须添加“…或对X类型的引用”(想想cast操作符)。因此,我有根据地猜测,这将是一个太大的负担,没有用处
C++具有以下类型
- 表达式的静态类型
仅称为“表达式类型”(若未另外指定动态表达式的含义)。这是表达式的一个属性,指定在编译时从表达式引用的内容中抽象出来的表达式类型。例如,如果a
引用int&
或int
变量,或者是一个文本0
,则所有这些表达式都具有类型int
- 左值表达式的动态类型
这是左值表达式引用的非基类对象的类型
ofstream fs("/log");
ostream &os = fs;
其中,os
具有流的静态类型ostream
和动态类型
- 对象或引用的类型
这是对象或引用实际具有的类型。一个对象总是有一个单一的类型,并且它的类型永远不会改变。但是什么对象存在于什么位置,只有在运行时才知道,所以一般来说,“对象类型”也是运行时的事情
ostream *os;
if(file)
os = new ofstream("/log");
else
os = new ostringstream;
由*os
表示的对象类型(以及左值的动态类型*os
)仅在运行时已知
int *p = new int[rand() % 5 + 1];
这里,由运算符new创建的数组的类型也只在运行时知道,并且(感谢)确实不能逃到静态C++类型系统。臭名昭著的别名规则(粗略地说,它禁止从不兼容的左值读取对象)提到了对象的“动态类型”,大概是因为它想强调运行时关注点的重要性。但严格地说,说对象的“动态类型”很奇怪,因为对象没有“静态类型”
- 变量或成员的声明类型
这是您在声明中提供的类型。相对于对象的类型或表达式的类型,这有时可能会有细微的不同
struct A {
A() { }
int a;
};
const A *a = new const A;
volatile const A *va = a;
这里,表达式a->a
具有类型const int
,但是a->a
解析为的成员的声明类型具有类型int
(成员实体)。由a->a
表示的对象类型具有类型const int
,因为我们创建了const a
对象
int &&x = 0;
int y = std::move(x);
int z = x;
enum A { X };
template<int Y> struct B { };