C++中的左值与右值

来源

    C++中的左值和右值其实是一个很久远的概念,但是逐渐到C++11才被重视起来。如今理解这两个概念对于正确运用C++11的一些特性十分有帮助。

    首要要知道这两个名词其实是继承C语言,C语言中是可以简单理解为:左值是赋值语句的左侧,右值则不能。然而在C++中,则不能简单的这么认为,但是可以归纳为:当一个对象被用作右值的时候,用的是对象的值(内容),当对象被用作左值的时候,用的是对象的身份(即在内存中的位置)。

    对于C++中的基本数据类型而言,基本和C语言中的使用相似,但是如果是自定义类型,则不同。

1) 对于基础类型,右值是不可被修改的,也不可被 const, volatile 所修饰

2) 对于自定义的类型,右值却允许通过它的成员函数进行修改。

#include <iostream>
using namespace std;
class Test{
public:
    Test(int a):_a(a){ }
    inline void show() const{
        cout<<_a<<endl;
    }
    inline void change(int a) {
        _a=a;
    }
private:
    int _a=3;
};

int main(){
    int lvalue=int(4);
    //int(3)=lvalue;这样是不行的,int(3)产生一个基础类型右值,是不可修改的
    cout<<lvalue<<int(5)<<endl;
    Test(5).change(6);//自定义类型右值可以通过成员函数修改
    const Test& tmp=Test(7);
}

    右值的两个基本特性:

1) 允许调用成员函数。

2) 只能被 const reference 指向。

   一个重要的原则是当需要右值的地方可以用左值来替代,但是不能把右值当成左值(也就是位置)使用。同时,左值与右值最大的区别:左值持久,右值短暂。左值可以有持久的状态,而右值要么是字面常量,要么是表达式求值过程中创建的临时对象。

左值引用和右值引用

    理解了左值和右值的基本概念和特点,就来区分一下C++11的新特性:左值引用和右值引用。对于常规的引用操作,就是左值引用,注意其不能绑定到要求转换的表达式、字面常量或是返回右值的表达式。

    右值引用是必须绑定到右值的引用,通过&&来表示,其重要的特质是只能绑定要一个即将销毁的对象,即可以绑定到要求转换的表达式、字面常量或是返回右值的表达式,不能将右值绑定到一个左值上(但是可以通过move来获得绑定到左值上的右值引用)。

int i = 42; //变量是左值
int &r = i;
int &&rr = i;//错误,不能将一个右值绑定到一个左值
int &r2 = i*42;//错误,i*42是右值
const int &r3 = i*42//正确,可以将一个const引用绑定在右值上
int &&rr2 = i*42;//正确

std::move

    首先要说明一下,由于移动源对象具有不确定的状态,对于std::move的使用是有风险的,在使用的时候,一定要确保move对象没有其他用户,虽然使用move可以大幅度提升性能,但是也有可能产生难以查找的错误。

    一般我们对左值进行拷贝,对右值进行移动。std::move将左值转换成右值,并赋予它“可移动的语义”

#include <iostream>
#include <utility>
#include <vector>
#include <string>
 
int main()
{
    std::string str = "Hello";
    std::vector<std::string> v;
 
    // 使用 push_back(const T&) 重载,
    // 表示我们将带来复制 str 的成本
    v.push_back(str);
    std::cout << "After copy, str is \"" << str << "\"\n";
 
    // 使用右值引用 push_back(T&&) 重载,
    // 表示不复制字符串;而是
    // str 的内容被移动进 vector
    // 这个开销比较低,但也意味着 str 现在可能为空。
    v.push_back(std::move(str));
    std::cout << "After move, str is \"" << str << "\"\n";
 
    std::cout << "The contents of the vector are \"" << v[0]
                                         << "\", \"" << v[1] << "\"\n";
}

//输出结果
//After copy, str is "Hello"
//After move, str is ""
//The contents of the vector are "Hello", "Hello"

 

 

参考 《C++ Primer》

https://www.cnblogs.com/catch/p/3500678.html

https://zh.cppreference.com/w/cpp/utility/move

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值