std::move()的学习总结

目录

1. 移动语义

2. std::move的实现及使用

3. 总结


1. 移动语义

移动语义可以使得编译器使用不那么昂贵的移动操作,来替换昂过的复制操作。同拷贝构造函数、拷贝赋值运算符赋予人们复制意义的能力一样,移动构造函数、移动赋值运算符也赋予人们移动语义的能力。更通俗的说:移动语义是通过移动构造函数或者移动赋值运算符实现的

移动语义的本质:所有权的转换!

举个例子,对于C++标准库提供的std::shared_ptr智能指针,当对其进行复制操作时,需要增加其引用计数,而引用计数是个原子类型,因此增加引用计数是个耗时操作;而当对其进行移动操作的时候,则引用计数会保持不变,也即无需进行引用计数的操作。

2. std::move的实现及使用

C++11中std::move强制将实参转换成右值引用的模板函数。其在C++11中的一个实现示例如下:

template <typename T>
typename std::remove_reference<T>::type&& 
move(T&& param) {
     using return_type = typename std::remove_reference<T>::type&&;
     return static_cast<return_type >(param);
 }

由上述实现可知,std::move是将参数强制转换成右值引用。而当某个参数被转换成右值引用后,便可以有机会通过移动构造函数或者移动赋值运算符进行移动操作。

下面以类A来进行说明其实现操作,类A的定义如下:

class A {
public:
    A() {
        std::cout << "A constructor" << std::endl;
    }

    A(const A& lhs) {
        std::cout << "copy constructor" << std::endl;
    }

    A(A&& rhs) {
        std::cout << "move constructor" << std::endl;
    }

    virtual ~A() {}
};

其测试代码以及测试结果如下:

int main() {
    A a;
    A b = a;
    A c = std::move(a);

    return EXIT_SUCCESS;
}


A constructor
copy constructor
move constructor

可以看到因为std::move将a转换成右值,因此此时c通过移动构造函数进行初始化。

思考一个问题:std::move()一定会导致移动发生么?

std::move不一定会保证移动操作的发生。

考虑下面这种情况,当我将上述测试代码中的A a声明成 const A a时,测试的结果会怎样?下面是测试的结果:

A constructor
copy constructor
copy constructor

原因就是,std::move的参数是个万能引用,当你传入一个const 对象的左值时,此时const属性依然会成为其参数的一部分,因此此时,移动构造函数便无法成为候选者,只有拷贝构造函数会成为候选者,故此时会调用拷贝构造函数,产生上述结果。

3. 总结

由上可知,C++11中的std::move 仅仅是将实参强制转换成右值引用,除此之外便没有任何作用。 而移动语义主要是由对象的移动构造函数或者移动赋值运算符实施。 并且std::move后并不能保证一定会实施移动语义

增加:

欢迎大家关注公众号互相交流(松元漫话)

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

qls315

感觉好可打赏几毛钱增强更新动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值