std::move
21天是肯定没法学会C++的。22天也不行。
C++11里引入了一个新的概念 :移动。 这个概念说简单其实很简单,因为它是介于拷贝和引用之间的一种概念。但还是有很多小伙伴表示不理解移动到底做了什么,如何理解移动。
要想理解移动,先来介绍一个概念:左值与右值。
左值与右值
笼统来讲,左值就是能够对其取地址的值。反之就是右值(临时变量也是右值)。比如1
, 2.0
, true
, nullptr
这种纯值类型,就是妥妥的右值。再比如 int a = 100;
, a
是左值,100
是右值。在给a
赋值的过程中,我们将右值拷贝到了左值。(其实并不是完全这样,编译器会做一定程度的优化,但为了方便理解,我们不考虑编译器的功劳)
两个栗子
在早期C++里,我们通常用指针或者引用来传递一个大变量,因为可以避免一次拷贝的开销。第一个栗子:如果我们有一个比较大的右值变量,我想将它传递给其他的函数,该如何避免/减少拷贝的开销呢?比较熟悉的朋友可能会说,我们可以传递 const &
来避免拷贝的开销。
没错,在C++11 之前,const &
可以对右值直接取引用。这样我们可以传递引用来避免拷贝的开销。那么下一个栗子就是,如果我们有一个比较大的右值变量,我想将它传递给其他的函数,又想要修改这个右值变量的值,该如何避免/减少拷贝的开销呢?
C++11 提出了一个概念:右值引用。语法是两个&。 它允许我们对右值进行直接引用。
移动
理解了右值之后,我们来思考一个问题。当我们进行赋值语句时,其实是构建了一个右值,然后复制给了左值。那么有没有花销更小的方法呢?答案就是移动。
熟悉C++的都知道C++中有构造方法。构造方法又有拷贝构造和赋值构造两种特殊的构造方法。C++11提出了新的构造类型:移动构造。也即方法接受的参数是一个右值,然后通过移动的方式,减少拷贝与销毁的开销,实现资源的转移。样式为: Type::Type(Type && rval)
另一个作用就是,std::move
在移动的时候,可以 剥夺原变量的数据所有权。通常进行所有权转移时我们会显式调用std::move
方法。
以vector
来举例。
vector<int> a {1,2,3,4,5}; for (auto i : a){ cout << i<< ", "; // --> 1, 2, 3, 4, 5 } vector<int> b = move(a); for (auto i : a){ cout << i<< endl; // Nothing, moved to b } cout << "----" <<endl; for (auto i :b){ cout << i<< ", "; // --> 1, 2, 3, 4, 5 }
联通
C++ 11 中的移动语义使得我们在构造临时变量,减少构造与析构的消耗,并且可以显示表达所有权的转移。既增强了代码的运行效率,又增加了代码的可读性。
move不产生新变量,它只是c++的搬运工。
Abc
如果我们有一个比较大的右值变量,我想将它传递给其他的函数,又想要修改这个右值变量的值,该如何避免/减少拷贝的开销呢?
引用啊
andy
右值引用是11新有的啊,之前没有
zzzzeno
博主这几篇博客真的写的很不错,短小精悍、深入浅出,学到了,感谢