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

Cal*_*vin 14 c++ compiler-construction performance pass-by-value pass-by-const-reference

看看这个假设的头文件:

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

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

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

一些可能相关的事情:

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

Dar*_*rda 8

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:
    ...
};
Run Code Online (Sandbox Code Playgroud)

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

  • 像往常一样,Boost人已经想到了这一点.:D看起来简短的答案是"不,没有办法哄骗编译器为你做这件事",而长期答案是"好吧,Boost在某些情况下设法解决了这个问题." 谢谢! (2认同)