C++11带来的move语义
C++11引入了move语义,stl中的容器基本都支持move语义,因此我们在使用stl中的容器的时候,就已经使用过move语义了,在网上看了不少关于move语义的文章,发现要讲move,左值和右值是必须讲的,那我们首先就来说说这个左值和右值。
左值和右值(c++中的左值与右值)
在 C中,左值指的是既能够出现在等号左边也能出现在等号右边的变量(或表达式),右值指的则是只能出现在等号右边的变量(或表达式)
在C++中,对于内置的类型,右值是不可被修改的,也不可被 const, volatile 所修饰;对于自定义的类型(user-defined types),右值却允许通过它的成员函数进行修改,其他同C一样,至于有些文章上说:左值就是可以取地址的,而右值不可取地址,个人认为这是不对的。
Move语义
先举个例子,这个例子也是最简单容易理解的
调用函数doubleValues时是有两次复制的,一次是在函数返回时,因为local变量要被回收,所以需要copy构造一个临时对象来返回,当返回这个临时对象后,又需要一次copy赋值操作来赋值给其他变量。你可能会说,不返回对象就可以啊,可以返回一个引用或者一个指针,但是要这样做就得分配内存,但是C++的一个设计目标就是尽量少分配内存。上述更糟糕之处在于,返回的临时对象使用完之后是会被销毁掉的。
右值引用的一个用处是可以用来创建move构造函数和move赋值操作符,当出现上述的情况时,不会调用赋值构造函数或者拷贝构造函数,而是调用move类型的拷贝或者赋值构造函数。
如果使用的是stl中的容器,那么move是默认支持的,在一些特殊情况下,move比引用更好,更能提高代码性能,相信在C++11之后,move是一大趋势,不过这对C++程序员的要求又提升不少。比如要实现自己的类,最好提供move版的拷贝和赋值构造函数,类似如下声明:
Class(const Class& other)
Class(Class&& other)
如果一个类提供了如上的拷贝构造函数,那么当其是右值引用的时候,就会调用类似上述第二种拷贝构造函数,而右值引用的拷贝构造函数在拷贝的时候,只拷贝起指针,而指针指向的东西是不会被拷贝的,因为右值引用的变量(这样叫可能不合理)编译器确定后边是不会在用到,比如文中返回stl::vector数组的情况,不论是变量values还是临时拷贝的返回值都在后续中不会被使用。
注:文中的文章链接,都是个人觉着不错的文章,对作者在理解一些概念上又很大帮助,提供出来也是为了大家能更好的理解。
C++11引入了move语义,stl中的容器基本都支持move语义,因此我们在使用stl中的容器的时候,就已经使用过move语义了,在网上看了不少关于move语义的文章,发现要讲move,左值和右值是必须讲的,那我们首先就来说说这个左值和右值。
左值和右值(c++中的左值与右值)
在 C中,左值指的是既能够出现在等号左边也能出现在等号右边的变量(或表达式),右值指的则是只能出现在等号右边的变量(或表达式)
在C++中,对于内置的类型,右值是不可被修改的,也不可被 const, volatile 所修饰;对于自定义的类型(user-defined types),右值却允许通过它的成员函数进行修改,其他同C一样,至于有些文章上说:左值就是可以取地址的,而右值不可取地址,个人认为这是不对的。
Move语义
先举个例子,这个例子也是最简单容易理解的
vector doubleValues (const vector& v) { vector new_values( v.size() ); for (auto itr = new_values.begin(), end_itr = new_values.end(); itr != end_itr; ++itr ) { new_values.push_back( 2 * *itr ); } return new_values; }
右值引用的一个用处是可以用来创建move构造函数和move赋值操作符,当出现上述的情况时,不会调用赋值构造函数或者拷贝构造函数,而是调用move类型的拷贝或者赋值构造函数。
如果使用的是stl中的容器,那么move是默认支持的,在一些特殊情况下,move比引用更好,更能提高代码性能,相信在C++11之后,move是一大趋势,不过这对C++程序员的要求又提升不少。比如要实现自己的类,最好提供move版的拷贝和赋值构造函数,类似如下声明:
Class(const Class& other)
Class(Class&& other)
如果一个类提供了如上的拷贝构造函数,那么当其是右值引用的时候,就会调用类似上述第二种拷贝构造函数,而右值引用的拷贝构造函数在拷贝的时候,只拷贝起指针,而指针指向的东西是不会被拷贝的,因为右值引用的变量(这样叫可能不合理)编译器确定后边是不会在用到,比如文中返回stl::vector数组的情况,不论是变量values还是临时拷贝的返回值都在后续中不会被使用。
注:文中的文章链接,都是个人觉着不错的文章,对作者在理解一些概念上又很大帮助,提供出来也是为了大家能更好的理解。