C++完美转发

lil*_*lzz 3 c++

1)

template<typename T, typename Arg> 
  shared_ptr<T> factory(Arg arg)
  { 
    return shared_ptr<T>(new T(arg));
  } 
Run Code Online (Sandbox Code Playgroud)

2)

template<typename T, typename Arg> 
  shared_ptr<T> factory(Arg& arg)
  { 
    return shared_ptr<T>(new T(arg));
  } 
Run Code Online (Sandbox Code Playgroud)

3)

template<typename T, typename Arg> 
  shared_ptr<T> factory(Arg const & arg)
  { 
    return shared_ptr<T>(new T(arg));
  } 
Run Code Online (Sandbox Code Playgroud)

*)为什么3号比1号和2号更受欢迎?

*)如果调用工厂(41),为什么要调用右值?

*)#define BOOST_ASIO_MOVE_ARG(type)type &&.在这种情况下什么是&&?

yzt*_*yzt 10

实际上,方法#3 并不比1和2好.这完全取决于T构造函数.

一种有点标准的方法是使用rvalue引用,&&你提到它.

所以,一个更好的工厂将是这样的:(这实际上是完美的转发)

template<typename T, typename Arg> 
std::shared_ptr<T> factory(Arg && arg)
{
    return std::shared_ptr<T>(new T (std::forward<Arg>(arg)));
}
Run Code Online (Sandbox Code Playgroud)

由于参考 C++的折叠规则,这个函数可以接受(并转发)rvalue refences和lvalue引用,也就是说,如果你传递一个rvalue,它会忠实地将rvalue转发T给它的构造函数,如果给它一个左值,这两种reference(Something & && arg)将崩溃,并且左值引用将被转发到底层构造函数.

我想我在这里覆盖了你的问题,但要明确回答,

  • #3 不是这里的首选方法.即使在C++ 11之前,您可能也想要函数的两者const&&重载factory.该const&版本是更好的,它实际上会接受临时值,但如果你的基础T类型有接受非const ref上的构造函数,那么你会得到一个编译错误,因为const&没有隐含浇铸为&.
  • 因为你不能获取文字的地址41(这在技术上并非100%正确,但我认为以这种方式考虑左值和右值是可以的.)
  • 它表示一个rvalue reference.你需要阅读这个; 一个解释不适合这里,并且已经有几个伟大的只是谷歌搜索!

更新:正如在评论中切向提到的那样,使用make_shared可能比shared_ptr使用刚刚new指针构造一个更好.make_shared通过分配控制块(包括引用计数)以及对象本身可以实现更高的效率,这将在访问引用计数器和对象时提供更好的缓存局部性,并且还可以节省一个内存分配.即使实现没有优化,也不会比上面的版本差.所以std::make_shared尽可能使用!这就是你在这里做的方式:

template<typename T, typename Arg> 
std::shared_ptr<T> factory (Arg && arg)
{
    return std::make_shared<T>(std::forward<Arg>(arg));
}
Run Code Online (Sandbox Code Playgroud)