开发者社区> 问答> 正文

表达式左值右值(C++学习) 区分? const vs non-const 右值引用 移动语义:报错

左值右值是表达式的属性,该属性称为 value category。按该属性分类,每一个表达式属于下列之一:

lvalue

left value,传统意义上的左值

xvalue

expiring value, x值,指通过“右值引用”产生的对象

prvalue

pure rvalue,纯右值,传统意义上的右值(?)

而 xvalue 和其他两个类型分别复合,构成:

lvalue + xvalue = glvalue

general lvalue,泛左值

xvalue + prvalue = rvalue

右值

区分?

++x 与 x++ 假定x的定义为 int x=0;,那么前者是 lvalue,后者是rvalue。前者修改自身值,并返回自身;后者先创建一个临时对像,为其赋值,而后修改x的值,最后返回临时对像。

区分表达式的左右值属性有一个简便方法:若可对表达式用 & 符取址,则为左值,否则为右值。比如

&obj , &*ptr , &ptr[index] , &++x

有效

&1729 , &(x + y) , &std::string("meow"), &x++

无效

对于函数调用,根绝返回值类型不同,可以是lvalue、xvalue、prvalue:

  • The result of calling a function whose return type is an lvalue reference is an lvalue

  • The result of calling a function whose return type is an rvalue reference is an xvalue.

  • The result of calling a function whose return type is not a reference is a prvalue.

const vs non-const

左值和右值表达式都可以是const或non-const。

比如,变量和函数的定义为:

string one("lvalue");
const string two("clvalue");
string three() { return "rvalue"; }
const string four() { return "crvalue"; }

那么表达式:

表达式

分类

one

modifiable lvalue

two

const lvalue

three()

modifiable rvalue

four()

const rvalue

引用

Type&

只能绑定到可修改的左值表达式

const Type&

可以绑定到任何表达式

Type&&

可绑定到可修改的左值或右值表达式

const Type&&

可以绑定到任何表达式

重载函数

#include <iostream>
#include <string>
using namespace std;

string one("lvalue");
const string two("clvalue");
string three() { return "rvalue"; }
const string four() { return "crvalue"; }

void func(string& s)
{
    cout << "func(string& s): " << s << endl;
}

void func(const string& s)
{
    cout << "func(const string& s): " << s << endl;
}

void func(string&& s)
{
    cout << "func(string&& s): " << s << endl;
}

void func(const string&& s)
{
    cout << "func(const string&& s): " << s << endl;
}

int main()
{
    func(one);
    func(two);
    func(three());
    func(four());
    return 0;
}

结果:

func(string& s): lvalue
func(const string& s): clvalue
func(string&& s): rvalue
func(const string&& s): crvalue

如果只保留const string& 和 string&& 两个重载函数,结果为:

func(const string& s): lval

展开
收起
kun坤 2020-06-06 19:55:43 987 0
1 条回答
写回答
取消 提交回答
  • lz你好,右值引用当中:

    int main() {  int && a=1;  F2(a);  F1(a);  F2(2);  F1(2);  return 0; }

    F2(a)会出现编译错误,因为具名右值引用传参时会作为左值,而F2中的参数int &&a 只能绑定非常量右值,而不能绑定左值。

    还有你说“对函数的右值引用无论具名与否都将被视为左值”,经过试验只有具名函数的右值引用才会作为左值,而非具名则会作为右值.

    试验代码:

    #include<iostream>
    #include<algorithm>
    using std::cout;
    using std::endl;
    void F1(int &a)
    {
    cout<<"左值引用"<<endl;
    }
    void F1(int && a)
    {
    cout<<"右值引用"<<endl;
    }
    int test()
    {
    return 1;
    }


    int main()
    {
      int &&a = test();//具名函数右值引用
    F1(a);//非常量左值引用只能绑定非常量左值,所以具名函数右值引用会作为左值调用F1(int &a)
    F1(test());//非常量右值引用只能1绑定非常量右值,所以非具名函数作为右值调用F1(int &&a)


    return 0;
    }
    模板参数类型当中:

    template <typename Type> void Swap(Type&& sb1, Type&& sb2) {  Type sb(sb1);  sb1 = sb2;  sb2 = sb; }
    sb1和sb都是非常量右值引用,他们是不能绑定作为左值的具名右值引用的。

    参见博客:http://www.cnblogs.com/hujian/archive/2012/02/13/2348621.html

    2020-06-06 19:55:51
    赞同 展开评论 打赏
问答分类:
C++
问答地址:
问答排行榜
最热
最新

相关电子书

更多
使用C++11开发PHP7扩展 立即下载
GPON Class C++ SFP O;T Transce 立即下载
GPON Class C++ SFP OLT Transce 立即下载

相关实验场景

更多