大家好,欢迎来到IT知识分享网。
在C++11中引入了move语义,所以在拷贝一个对象的时候,我们需要思考,这个对象所持有的资源,能不能被偷取。
- 不能被偷取,那么拷贝的时候就调用拷贝构造函数(const T&)
- 是个将亡值,资源能被偷取,那么拷贝的时候就需要调用移动构造函数(T&&)
所以,这样一个拷贝函数,需要解决两个难题:
1、能够同时接受左值和将亡值。
2、保证值的类型,在传入函数和传出函数时,不变。
folly中实现了这样一个copy函数,位于
folly/Utility.h
代码分析
template <typename T> constexpr std::decay_t<T> copy(T&& value) noexcept(noexcept(std::decay_t<T>(static_cast<T&&>(value)))) { return static_cast<T&&>(value); }
主要通过两种技巧解决了开头所说的两个问题:
1、万能引用,能同时接受左值和将亡值
template <typename T> constexpr std::decay_t<T> copy(T&& value);
上述函数模板中的T最后会被推导为表达式value的值类型,假设传入一个int类型的值:
- value为左值,则T被推导为int&
- value为将亡值,则T被推导为int&&
2、完美转发用来保证表达式的值类型不改变
static_cast<T&&>(value)
T被用来保存表达式的值类型,所以可以利用C++中引用折叠的特征,来还原表达式原本的值类型:
- value为左值,则value的类型会被转化为
T&& ---> int& && ---> int&
- value为将亡值,则value的类型会被转化为 C++ T&& —> int&& && —> int&&
当然也可以使用,std::forward()来进行完美转发。
3、因为T中保存的是值的类型,所以返回值的类型我们需要去除&或者&&,来得到一个纯右值
constexpr std::decay_t<T>
到这里,函数会根据return变量的值类型,来自动选择调用拷贝构造,还是移动构造。
使用
struct person { person() { std::cout << "default constructor" << std::endl; } person(person&&) { std::cout << "movd constructor" << std::endl; } person(const person&) { std::cout << "copy constructor" << std::endl; } }; person p; // 传入一个将亡值 copy(std::move(p)); std::cout << "==============" << std::endl; // 传入一个左值 copy(p);
输出:
default constructor movd constructor ============== copy constructor
免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://yundeesoft.com/79631.html