您的位置:首页 > 编程语言 > C语言/C++

C++中的左值和右值

2016-04-20 14:54 369 查看

左值和右值的定义

从C中继承而来

左值:既能出现在等号左边也能出现在等号右边的变量(或表达式)。通常来说,有名字的变量即左值,且左值是在程序中能够寻址的东西。

右值:只能出现在等号右边的变量(或表达式)。由运算操作(加减乘除,函数调用返回值等)所产生的的中间结果(没有名字)即右值,右值是没法取得它的地址的。

在C++中的不同

对于内置的类型: 左值和右值的概念和C区别不大,右值是不可被修改的,也不可被const,volatile所修饰。

对于自定义的类型: 右值却允许通过它的成员函数进行修改,且能被const类型的引用所指向

左值引用,右值引用

举例代码:

class cs
{
public:
cs(int i): i_(i)
{
cout << "cs(" << i <<") constructor!" << endl;
}
~cs()
{
cout << "cs destructor,i(" << i_ << ")" << endl;
}

cs& operator=(const cs& other)
{
i_ = other.i_;
cout << "cs operator=()" << endl;
return *this;
}

int get_i() const
{
return i_;
}
void change(int i)
{
i_ = i;
}

private:
int i_;
};

cs get_cs()
{
static int i = 0;
return cs(i++);
}

int main()
{
// 合法
(get_cs() = cs(2)).change(323);
get_cs() = cs(2);// operator=()
get_cs().change(32);

return 0;
}


P.s.1 : 右值能被const类型的引用所指向

合法写法:

const cs& ref = get_cs();


Error:

cs& ref = get_cs();


即:当一个右值被const指向时,其生命周期就被延长(右值不能被当成左值使用,但左值能被当成右值使用)

P.s.2 : 非 const reference 不能引用 rvalue

void func(cs& c)
{
cout << "c:" << c.get_i() << endl;
}
//合法:
func(get_cs() = get_cs() );
//error
func(get_cs());


P.s.3 : 不同的拷贝复制函数

class cs
{
public:
cs& operator=(const cs& c);
};

// 另一种写法
class cs2
{
public:
cs2& operator=(cs2& c);
};


上面两种写法的不同之处就在于参数,一个是 const reference,一个是非 const。对于自定义类型的参数,通常来说,如果函数不需要修改传进来的参数,我们往往就按 const reference 的写法。

P.s.4 : 需要修改参数的值

// 类似auto_ptr
class auto_ptr
{
public:
auto_ptr(auto_tr& p)
{
ptr_ = p.ptr_;
p.ptr_ = NULL;
}

private:
void*  ptr_;
};


所以,对于 auto_ptr 来说,它的 copy constructor 的参数类型是 non const reference。有些情况下,这种写法应该被鼓励,毕竟 non const reference 比 const reference 更能灵活应对各种情况,从而保持一致的接口类型,当然也有代价,参数的语义表达不准确了。除此更大的问题是如果拷贝构造函数写成这样子,却又对 rvalue 的使用带来了极大的不变,如前面所讲的例子,rvalue 不能被 non const reference 所引用,所以像 auto_ptr 的这样的类的 copy constructor 就不能接受 rvalue.

举个栗子:

//错误
auto_ptr p(get_ptr());

//operator=() 同理,错误
auto_ptr p = get_ptr();


这也是 auto_ptr 很不好用的原因之一,为了解决这个问题,c++11 中引入了一种新的引用类型,该种引用是专门用来指向 rvalue 的,有了这种新类型,对 lvalue 和 rvalue 的引用就能明确区分开来了。因为有了这种新的类型,接着就引出了 c++11 中新的语义,move(), forward() 等.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  c++