std::move()的学习总结

目录

1. 移动语义

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

3. 总结


1. 移动语义

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

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

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

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

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

template 
typename std::remove_reference::type&& 
move(T&& param) {
     using return_type = typename std::remove_reference::type&&;
     return static_cast(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后并不能保证一定会实施移动语义

增加:

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

std::move()的学习总结_第1张图片

 

你可能感兴趣的:(C++基础知识总结,c++,编程语言,设计模式)