C++中的左值和右值

左值和右值的定义

  1. 从C中继承而来

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

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

  2. 在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() 等.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值