C++ 什么表达式创建XValue?
我试图理解C++11的概念 我的标准草案说: xvalue(一个“到期”值)也指一个对象,通常在其生命周期结束时(因此 例如,可以移动资源)。xvalue是某些类型表达式的结果,这些表达式涉及 右值参考(8.3.2)。[示例:调用返回类型为右值的函数的结果 引用是一个xvalue。-结束示例] 好的,那么产生xvalue的“特定类型的表达式”到底是什么呢?规范的这一部分没有详细说明这些表达式的列表C++ 什么表达式创建XValue?,c++,c++11,language-lawyer,xvalue,C++,C++11,Language Lawyer,Xvalue,我试图理解C++11的概念 我的标准草案说: xvalue(一个“到期”值)也指一个对象,通常在其生命周期结束时(因此 例如,可以移动资源)。xvalue是某些类型表达式的结果,这些表达式涉及 右值参考(8.3.2)。[示例:调用返回类型为右值的函数的结果 引用是一个xvalue。-结束示例] 好的,那么产生xvalue的“特定类型的表达式”到底是什么呢?规范的这一部分没有详细说明这些表达式的列表 我理解左值和prvalue(至少我认为我理解)。在§5(C++11§5[expr]/6)的介绍中有
我理解左值和prvalue(至少我认为我理解)。在§5(C++11§5[expr]/6)的介绍中有一个有用的非规范性注释: [注意:如果表达式是:
- 隐式或显式调用其返回类型为对对象类型的右值引用的函数的结果
- 对对象类型的右值引用的强制转换
- 类成员访问表达式,指定非引用类型的非静态数据成员,其中对象表达式是xvalue,或
- 指向成员表达式的
指针,其中第一个操作数是xvalue,第二个操作数是指向数据成员的指针*
void move_test(){
std::string s = "I'm here!";
std::string m = std::move(s); // move from <s> to <m>
// s is now in an undefined, but valid state;
std::cout << "s=" << s << "; &s=" << &s << std::endl;
}
结构A{
int m;
};
A&&运算符+(A,A);
A&&f();
A A;
A&&ar=静态(A);
表达式f()
、f().m
、static\u cast(a)
和a+a
都是x值。表达式ar
是左值
获取xvalue表达式有两种常见方法:
- 使用
移动对象<代码>标准::移动对右值引用类型执行std::move
,并返回右值引用静态转换
- 使用
转发右值std::forward
通常用于函数模板中,以实现函数参数的完美转发 如果提供给函数模板的参数是右值,则参数类型将是右值引用,这是一个左值。在这种情况下,std::forward
对右值引用类型执行std::forward
,并返回右值引用 (注意:如果提供给函数模板的参数是左值,则参数类型将是左值引用,static\u cast
将返回左值引用。)std::forward
std::move
,有时是std::forward
5.2.5第4段:如果E2
是非静态数据成员。。。如果E1
是一个x值,则E1.E2
是一个x值
(另一方面,数据成员查找E1->E2
始终是左值。)
类似地,如果E1
是一个x值,那么数据成员查找E1.*E2
是一个x值:
5.5第6段:*
表达式的第二个操作数是指向数据成员的指针,其结果与其第一个操作数具有相同的值类别(3.10)
对于各种类型的强制类型转换:
:5.2.7第2段dynamic\u cast(expr)
:5.2.9第1段static\u cast(expr)
:5.2.10第1段重新解释铸件(expr)
:5.2.11第1段const_cast(expr)
:5.4第1段(类型)expr
Type
是对对象类型的右值引用时,表达式才是xvalue。这同样适用于类型(expr)
,因为
5.2.3第1段:如果表达式列表[在类型名称后面的括号中]是单个表达式,则类型转换表达式与相应的强制转换表达式(5.4)等效(定义明确,含义明确)
(另一方面,Type{expr}
始终是一个PR值。)
关于条件运算符的第5.16节最后说A?B:C
如果B和/或C是xvalue,则有时可以是xvalue。但完整的规则很难总结
如果表达式最终调用用户定义的重载运算符函数,则第5.2.2节适用于该表达式,而不是描述内置运算符行为的表达式。(参见@James poster示例中的表达式
a+a
)我从阅读中得出的结论是,将某物称为xvalue是一种奇特的表达方式:
xvalue只是一个右值,其存储可能已被释放,因此使用它意味着您必须自己验证它的存在
通常,它是一个或多个级别的间接指向,与实际的右值不同
相反,右值的存储空间保证为l
void move_test(){
std::string s = "I'm here!";
std::string m = std::move(s); // move from <s> to <m>
// s is now in an undefined, but valid state;
std::cout << "s=" << s << "; &s=" << &s << std::endl;
}