C++右值引用-好东西
解决C++中临时变量的好方法-右值引用,可在visual studio 2010中试试
右值引用和移动语义(rvalue references, move semantics)
该特性比较晦涩,但用途很明确。
* 移动语义
考虑swap函数
template <class T> swap(T& a, T& b)
{
T tmp(a); // now we have two copies of a
a = b; // now we have two copies of b
b = tmp; // now we have two copies of tmp (aka a)
}
用C++0x 的rvalue references特性,代码可以这样写了
template <class T> swap(T& a, T& b)
{
T tmp(std::move(a)); // 移动构造:移动临时变量a的值来构造tmp
a = std::move(b); // 移动赋值:将变量b的值移动到a
b = std::move(tmp); // 移动赋值:将临时变量tmp的值移动到b
}
这里就增了一个新的构造/赋值语义,首先温习一下C++的拷贝构造和拷贝赋值:
A(const A& a);
A& operator=(const A& a);
按照C++标准,临时变量如上面的foo返回的变量可以作为拷贝语义的变量,但只能以const&类型传递进。由于这个限制,想要为vector创造移动的语义(将内部的指针转移到另外一个变量而不产生额外的销毁操作)就不可能了。因为你没法修改 a 的变量,也就没法让临时变量在析构的时候不销毁其拥有的数据。
所以有了rvalue refs, 这个新增的构造语义就是移动语义,分别是移动构造和移动赋值
A(A&& a);
A& operator=(A&& a);
对于vector,实现这两个操作的可能逻辑就是:对于移动构造,取得a的内部指针,并将其清0;对于移动赋值,交换对象和a的内部指针。
这样以来,最初的问题就解决了。
标准库提供了 std::move 通用模板函数为变量或函数创建这种语义环境,比如:
vector<t> v1,v2;
v2 = v1; // 调用拷贝赋值
v2 = std::move(v1); //调用移动赋值
注意,如果t是不可拷贝类型,比如臭名昭著的smart_ptr<t>,那么这里的拷贝赋值则根本没法使用,因为vector的每个变量都无法被拷贝,而移动构造赋值则可以正确被调用。这也就是smart_ptr臭名昭著的原因所在,他根本没法和 stl 库配合使用,当然值得庆幸的是,C++0x已经收录了全能的 shared_ptr 了。
* 参数转移
还有一个功能是参数转移,以及新的 std::forward 通用模板函数。
所谓参数转移就是一个模板函数将其参数转移给另一个函数,听上去很容易,但目前C++里有个很麻烦的问题。还是因为临时变量,为了能够同时传递临时变量和左值变量,必须为每个参数提供两个版本的重载,比如:
template <class T>
void foo(const T& t)
{
goo(t);
}
template <class T>
void foo(T& t)
{
goo(t);
}
如果有两个参数,就有4个版本,如果有三个参数,就有8个版本。有了右值引用事情就简单多了:
template <class T>
void foo(T&& t)
{
goo(std::forward(t));
}
另外配合另外一个C++0x特性“变长函数模板”,就可以完美的实现函数代理了。比如将所有foo(a, b …)函数转移到调用goo(somevar, a, b, …)。
所以总的来说,右值引用的出现是作为语言的一个重要的完备性补充:以前作为右值的临时变量传递给函数时只能拷贝或者转换为常左值引用(const lvalue reference),现在则可以使用右值引用来捕获传递临时变量了。 其直接的作用就是产生了新的构造/复制语义,和新的参数转移方法。
参考文档
- C++0x on Wikipedia http://en.wikipedia.org/wiki/C%2B%2B0x#Rvalue_reference_and_move_semantics
- 关于右值引用和移动语义更详细的描述 http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2006/n2027.html
作者:老纪
原载:老纪博客版权所有。转载时必须以链接形式注明转载自老纪博客 [http://www.jifuyi.com/]。
本文链接地址:http://www.jifuyi.com/c-plus-plus%e5%8f%b3%e5%80%bc%e5%bc%95%e7%94%a8-%e5%a5%bd%e4%b8%9c%e8%a5%bf/
老纪,一个三十好几的老程序员,不知不觉蹉跎了不少岁月,心中曾有的萌动没有一丝的记忆,所以现在能记的就记,能写的就写。软件的开发、技巧,互联网的时讯、要闻,新科技的发展、评论,个人的感悟、随想就统统的让它跃然于老纪博客上。
sink
2010年06月06日
先留言再看文章~还有,好像发现你的验证码每次都是wave哦!~
老纪
2010年06月06日
呵呵,这个验证码就认你了,其实它是多少也无所谓,只要能防住大部分的垃圾评论就可以了