C++11在运行期有所增强,通过增加核心的右值引用机制来改善临时对象导致的效率低下的问题。C++临时对象引入了多余的构造、析构及其内部资源的申请释放函数调用,导致程序运行时性能受损,这一点被广为诟病。C++标准委员会在C++11中引入了右值引用这个核心语言机制,来提升运行期性能。右值引用机制要能发挥威力,需要多种设施支持。这里说一下其中的一个,标准库中的std::move模板方法。move语义涉及的代码很少,如下所示,我用的是vc10.0版本的STL库。
template<class _Ty> inline typename remove_reference<_Ty>::type&& move(_Ty&& _Arg) _NOEXCEPT { // forward _Arg as movable return ((typename remove_reference<_Ty>::type&&)_Arg); } template<class _Ty> struct remove_reference { // remove reference typedef _Ty type; }; template<class _Ty> struct remove_reference<_Ty&> { // remove reference typedef _Ty type; }; template<class _Ty> struct remove_reference<_Ty&&> { // remove rvalue reference typedef _Ty type; };
基于上面的代码,可以看出move语用是把变量强制转换成右值引用。既然理解了这个语用,我们可以不使用move函数来为需要右值引用的函数传递参数,在代码中可以直接使用“(_Ty&&)变量”的形式。可是,我们应该使用move函数而避免使用上述的强制转换,主要是基于下面的几点。
1:标准库中的move函数为转换成右值提供了一层抽象,能够更适应未知的未来。
2:标准库中的move函数只有很少的代码,性能会比之前的深度拷贝更好。
3:如果我们改变了变量的类型,产生右值引用的表达式可以不用改变。
4:相比int &&,move所写的字符很少。
从 template<class _Ty> struct remove_reference<_Ty&&>来看,move支持应用在右值引用类型变量上。一个右值引用变量传递到需要右值引用的函数中去,是否还需要move语句呢?照以前经验来推断的话,会觉得不必要了。实际上是必需的,考察下面的代码。
bool IsRvalue(const int&& ) { return true; } bool IsRvalue(int &) { return false; } bool IsRvalue(const int& ) { return false; } //bool IsRvalue(int ) //{ // return false; //} void Test(int &&rv) { printf("rv is a rvalue: %s\n", IsRvalue(rv)? "yes": "no"); printf("rv is a move(rvalue): %s\n", IsRvalue(move(rv))? "yes": "no"); } int _tmain(int argc, _TCHAR* argv[]) { int i = 5; Test(move(i)); system("pause"); return 0; }
运行上面的代码会发现IsRvalue(rv)会调用IsRvalue(int &)函数,究其原因是右值引用象引用一样,也是引用一个对象,在Test函数体中rv是一个引用。右值引用主要用于引用函数返回的临时对象,以期能够修改它来避免内部资源的深度拷贝。
5:既使是把一个右值引用对象匹配参数中的右值引用也必须使用move语句。