到底何时使用std::move


再最近的工程中,发现有滥用std::move的现象,现在对std::move在不同场景下的作用做一个简单分析与总结。
在c++编程中,为了提高程序运行的效率,可使用std::move来将一个左值转变成右值,或者说让被std::move包裹的变量具有可移动属性,能够将自身的持有的资源转移到另一个对象中。
那么何时该使用std::move呢,接下来我将通过一系列的试验程序来探索std::move在不同情况下的表现。

由基本类型构成的结构体

我们先定义一个由基本类型构成的结构体

struct TestStruct1{
    int a;
    char b;
};

然后测试TestStruct1在std::move中的具体表现:

	TestStruct1 t1;
    t1.a = 10;
    t1.b = 'a';

    printf("t1 value: a = %d b = %c  t1 address:a = %0x b = %0x \n",
            t1.a,t1.b,&t1.a,&t1.b);

    TestStruct1 t2(std::move(t1));
    printf("t1 value: a = %d b = %c  t1 address:a = %0x b = %0x \n",
            t1.a,t1.b,&t1.a,&t1.b);
    printf("t2 value: a = %d b = %c  t2 address:a = %0x b = %0x \n",
            t2.a,t2.b,&t2.a,&t2.b);

获得输出:

t1 value: a = 10 b = a  t1 address:a = 4feb39f8 b = 4feb39fc 
t1 value: a = 10 b = a  t1 address:a = 4feb39f8 b = 4feb39fc 
t2 value: a = 10 b = a  t2 address:a = 4feb3a00 b = 4feb3a04 

可以看到对基本的类型构造时使用std::move,其效果跟普通的赋值没有任何区别。

拥有指针的结构体

接下来我们让结构体中包含基本类型的指针

    struct TestStruct2{
        int* a;
        char* b;
    };

我们对这个结构体使用std::move,并查看输出

    TestStruct2 t1{new int[1],"Hello"};
    *(t1.a) = 2;
    printf("t1 value: a = %d b = %s t1 address:a = %0x b = %0x \n",
            *(t1.a),t1.b,t1.a,t1.b);
    TestStruct2 t2(std::move(t1));
    printf("t1 value: a = %d b = %s  t1 address:a = %0x b = %0x \n",
            *(t1.a),t1.b,t1.a,t1.b);
    printf("t2 value: a = %d b = %s  t2 address:a = %0x b = %0x \n",
            *(t2.a),t2.b,t2.a,t2.b);
t1 value: a = 2 b = Hello  t1 address:a = 6c948e70 b = 6bed1b6e 
t1 value: a = 2 b = Hello  t1 address:a = 6c948e70 b = 6bed1b6e 
t2 value: a = 2 b = Hello  t2 address:a = 6c948e70 b = 6bed1b6e

可以看出使用std::move的效果跟普通的赋值效果没有任何区别;

对string使用std::move

当对string使用std::move来调用其移动构造函数时,根据字符串长度的不同,会右不同的输出结果:
字符串较短时

    std::string t1 = "Hello";
    printf("t1 value:%s t1 address %0x \n",t1.c_str(),t1.c_str());
    std::string t2(t1);
    printf("t2 value:%s t2 address %0x \n",t2.c_str(),t2.c_str());
    std::string t3(std::move(t1));
    printf("t1 value:%s t1 address %0x \n",t1.c_str(),t1.c_str());
    printf("t3 value:%s t3 address %0x \n",t3.c_str(),t3.c_str());
t1 value:Hello t1 address ec190820 
t2 value:Hello t2 address ec190840 
t1 value: t1 address ec190820 
t3 value:Hello t3 address ec190860

字符串较长时

t1 value:Helloooooooooooooooooooooo t1 address 1e070e70 
t2 value:Helloooooooooooooooooooooo t2 address 1e0712b0 
t1 value: t1 address 87ef6a90 
t3 value:Helloooooooooooooooooooooo t3 address 1e070e70 

可以看到当字符串较短时,t3中字符串的地址跟t1中不相同,而字符串较长时t3中字符串的地址跟t1中的相同,意味着当字符串较长是,通过string的移动构造函数会直接将t1中的字符串地址给t3。

总结

从上述试验中可以看出,std::move的作用是将一个左值变成一个右值,以供移动构造函数使用。
如果一个变量并没有定义移动构造函数,那么其将调用默认的移动构造函数,其功能与普通的构造函数相同(如果变量内部的成员变量也没定义移动构造函数的话);
因此std::move应该用在自定义了移动构造函数的那些变量中。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值