繁体   English   中英

我可以让C ++编译器决定是按值传递还是按引用传递?

[英]Can I let the C++ compiler decide whether to pass-by-value or pass-by-reference?

看看这个假设的头文件:

template <class T>
class HungryHippo {
public:
    void ingest(const T& object);
private:
    ...
}

现在,对于HungryHippo<string>来说,你想要ingest对字符串的引用是有道理的 - 复制字符串可能非常昂贵! 但对于HungryHippo<int>它的含义却不那么明显。 直接传递一个int可能非常便宜(大多数编译器都会在寄存器中执行它),但是将引用传递给int是一个额外的不必要的间接级别。 这一切都适用于返回值。

有没有办法向编译器建议“嘿,我不会修改参数,所以决定是通过值还是通过引用来传递,这取决于你认为哪个更好”?

一些可能相关的事情:

  • 我可以通过编写template <class T, bool PassByValue> class HungryHippo然后专门研究PassByValue手动伪造这个效果。 如果我想得到真正的幻想,我甚至可以根据sizeof(T)std::is_trivially_copyable<T>来推断PassByValue 无论哪种方式,当实现看起来几乎相同时,这是一项额外的工作,我怀疑编译器可以更好地决定是否通过值传递。
  • libc ++项目似乎通过内联许多函数来解决这个问题,因此编译器可以选择一个级别,但在这种情况下,让我们说 ingest的实现相当复杂,不值得内联。 如注释中所述,默认情况下,所有模板函数都是inline的。

boost::call_traits标头正好处理这个问题。 在这里查看

具体来说, call_traits<T>::param_type选项包括以下描述:

如果T是一个小的内置类型或指针,那么param_type被定义为T const ,而不是T const& 如果它们依赖于传递的参数,这可以提高编译器优化函数体中循环的能力,否则传递参数的语义不变(需要部分特化)。

在您的情况下,您可以定义ingest如下:

template <class T>
class HungryHippo {
public:
    void ingest(call_traits<T>::param_type object);
    // "object" will be passed-by-value for small 
    // built-in types, but passed as a const reference 
    // otherwise
private:
    ...
};

这实际上是否会对您的实际代码/编译器组合产生很大影响,我不确定。 一如既往,你必须运行一些实际的基准测试,看看会发生什么......

虽然诸如boost提到的call_traits<T>之类的技巧做了他们声称在这种情况下做的事情,但我认为你假设编译器在最重要的情况下还没有进行这种优化。 毕竟,这是微不足道的。 如果你接受const T&sizeof(T) <= sizeof(void*) ,那么C ++引用语义强加的不变量允许编译器简单地在整个函数体中替换它,如果它是胜利的话。 如果不是,那么最坏情况的开销是函数序言中的一个指向arg的引用。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM