folly学习(三):C++中如何实现一个高效的拷贝函数

folly学习(三):C++中如何实现一个高效的拷贝函数在C++11中引入了move语义,所以在拷贝一个对象的时候,我们需要思考,这个对象所持有的资源,能不能被偷取。

大家好,欢迎来到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

(0)

相关推荐

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注

关注微信