C ++完美转发

时间:2013-08-31 01:51:28

标签: c++

1)

template<typename T, typename Arg> 
  shared_ptr<T> factory(Arg arg)
  { 
    return shared_ptr<T>(new T(arg));
  } 

2)

template<typename T, typename Arg> 
  shared_ptr<T> factory(Arg& arg)
  { 
    return shared_ptr<T>(new T(arg));
  } 

3)

template<typename T, typename Arg> 
  shared_ptr<T> factory(Arg const & arg)
  { 
    return shared_ptr<T>(new T(arg));
  } 

*)为什么数字3优先于数字1和数字2?

*)如果调用factory(41),为什么调用rvalue?

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

2 个答案:

答案 0 :(得分: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)));
}

由于引用折叠 C ++规则,此函数可以(并转发)rvalue refences和lvalue引用,即,如果你传递rvalue,它会忠实地将该rvalue转发给{ {1}}的构造函数,如果给它一个左值,那么两种引用(T)将会崩溃,并且左值引用将被转发到底层构造函数。

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

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

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

make_shared

答案 1 :(得分:1)

  

*)为什么数字3优先于数字1和数字2?

如果Arg不可复制,则

(1)将无效。 (2)不允许你传递右值,如factory<int>(42);

请注意,这三个示例都不涉及完美转发。我不确定你问题的主题是什么。

  

*)如果调用factory(41),为什么在rvalue上调用?

我不确定我理解这个问题。根据定义,41是一个右值。

  

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

type&&rvalue referencetype