概述
总之,在c++表达式不是左值,就是右值。
右值的特性:
1 右值不能取址,如&i++是无法编译的
2 右值不能赋值,即不能作为内建的赋值运算符和复合赋值运算符的左操作数。注意:此处强调的是内建,因为c++支持运算符重载,重载过的赋值运算符和复合赋值运算符,右值仍然可以作为左操作数
3. 右值可以初始化const左值引用(左值介绍参见https://blog.csdn.net/ant2012/article/details/91345255),且右值所标识的对象的生命周期会延长到该引用的作用域结尾
4. 右值可以初始化右值引用,且右值所标识的对象的生命周期会延长到该引用的作用域结尾
5. 在函数重载的情况下,一个是右值引用形参,一个是const左值引用形参,右值优先匹配右值引用
class Test {
public:
void operator = (int i) {
}
};
Test getTest() {
return Test();
}
int getInt() {
return 0;
}
int main(int argc, const char * argv[]) {
getTest() = 1; // valid
getInt() = 1;
// invalid, build error
const int& i = getInt(); // valid
int&& i = getInt(); // valid
return 0;
}
右值包含纯右值和亡值
纯右值:
1. 除了字符串之外的字面量。如42,true,nullptr
2. 返回类型为非引用的函数调用或运算符重载表达式。如str.substr(1, 2), str1 + str2
3. 内建的后置自增和自减表达式。如i++,i--
4. 内建的算术表达式。如i + j,i * j,i - j
5. 内建的逻辑表达式。如 i && i,i || j
6. 内建的比较表达式。如 i < j,i == j
7. 内建的取址表达式。如 &a
8. 对象成员表达式。如a.m,且m是成员枚举项(不是枚举变量)或者是非静态成员函数(参见下面的未决成员函数调用),或者a为右值且m为非引用类型的非静态数据成员。代码demo参见https://blog.csdn.net/ant2012/article/details/91345255第7条
9. 内建的指针成员表达式,如p->m,且m是成员枚举项(不是枚举变量)或者是非静态成员函数(参见下面的未决成员函数调用)
10. 对象的成员指针表达式,如a.*mp,且mp是成员函数指针(参见下面的未决成员函数调用),或者a是右值且mp是数据成员指针(c++11之前,c++11以后被归为亡值)
typedef int (Test::*MP); // 数据成员指针
MP mp = &Test::value;
getTest().*mp; // 右值
11. 内建的指针的指针成员表达式,如p->*m,且mp是成员函数指针(参见下面的未决成员函数调用)
12. 内建的逗号表达式,如a, b,其中b是右值,因为逗号表达式的值就是最后一个表达式的值
13. 三元条件表达式,即 a ? b : c,至于其什么情况为右值,详见条件表达运算符,个人经验是当b和c都是左值时,表达式才是左值,否则是右值(纯右值或亡值)
14. 转换为非引用类型的转型表达式,如static_cast<double>(x),(int)1
15. this指针
16. 枚举项(不是枚举变量)
17. 非类型模板形参,且其类型不能是类(c++20),也不能是左值引用
18. lambda表达式,如 [] () {std::cout << "qianll" << std::endl;}
19. requires表达式(c++20)
亡值:
1. 函数调用或重载运算符表达式,其返回类型为右值引用,如std::move(x)
2. 内建的下标表达式,如a[n],且a为右值
3. 对象成员表达式,如a.m,且a为右值,且m是非静态的非引用类型
4. 对象的成员指针表达式,如a.*mp,且a为右值且mp是数据成员指针
5. 三元条件表达式,即 a ? b : c,至于其什么情况为亡值,详见条件表达运算符,个人经验是当b和c都是左值时,表达式才是左值,否则是右值(纯右值或亡值)
6. 转换为右值引用的转型表达式,例如static_cast<int&&>(x)
7. c++17部分case
未决成员函数调用(Pending member function call)
表达式 a.mf 与 p->mf,其中 mf 是非静态成员函数,以及表达式 a.*pmf 与 p->*pmf,其中 pmf 是成员函数指针,被归类为纯右值表达式。但它们不能用来初始化引用,也不能作为实参,只能用来作为函数调用运算符的左操作数(即p.mf(args)),总之我理解的就是无法验证它是右值,但是它就是右值
参考:https://en.cppreference.com/w/cpp/language/value_category
加入我们:http://www.duoceshi.com/team.html
最后
以上就是诚心汽车为你收集整理的c++ 值类型之右值的全部内容,希望文章能够帮你解决c++ 值类型之右值所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复