【问题标题】:Providing functions versions where both by value and by reference are available提供按值和按引用都可用的函数版本
【发布时间】:2017-03-13 13:33:16
【问题描述】:

我定义了这个函数:

template <typename T>
void foo (T &result){
  //some very complicate stuff
  result = //something
}

现在,假设有时我想用T=int 调用它,在其他情况下用T=std::string 调用它。因此,在第二种情况下,标头是有效的,但带有 T=int this is inefficient。请注意,我仅使用这两种类型作为示例。

所以更好的解决方案是定义另一个函数:

template <typename T>
T foo(){
  T result;
  //some very complicate stuff
  return result;
}

并且让用户决定调用哪个版本,但是我们如何避免在函数中调用//some very complicate stuff的整个代码呢?

【问题讨论】:

  • 对整数引用进行操作效率相对较低,但成本并不高。只是因为复制一个整数也很便宜。

标签: c++ return pass-by-reference pass-by-value


【解决方案1】:

但是对于T=int,这是低效的

启用编译器优化,这很可能永远不会重要 - 重要的情况可以通过分析检测并单独处理。


但是我们如何避免在函数中调用//some very complicate stuff的整个代码呢?

好吧,避免它的一种可能方法是您需要传递一个函数对象作为额外参数:

template <typename T, typename F>
void foo (T &result, F&& complicated_stuff){
  std::forward<F>(complicated_stuff)();
  result = //something
}

template <typename T, typename F>
T foo(F&& complicated_stuff){
  T result;
  std::forward<F>(complicated_stuff)();
  return result;
}

这是一个很好的解决方案,极有可能会被编译器内联和优化...但是如果您要做的只是避免通过引用传递原始类型,那又有什么意义呢?我们在这里为函数对象添加了一个额外的转发引用


因此,我强烈建议您只使用一个版本的foo。按值返回的是更惯用的 C++11,并且不会比由于 RVO 和 move 语义 而采用引用的那个慢。

【讨论】:

  • 感谢您的有用回答。只有一个问题:为什么移动语义应该使return 方法不比另一个慢?
  • @justHelloWorld:在最好的情况下,您会得到 RVO/NRVO,它甚至不调用移动构造函数。在最坏的情况下,您会调用移动构造函数,这对于大多数数据结构的性能而言是微不足道的(因为它通常由 1-2 个指针分配组成)。
  • 感谢您的澄清
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-05-24
  • 1970-01-01
  • 2020-11-15
  • 1970-01-01
  • 1970-01-01
  • 2021-08-24
相关资源
最近更新 更多