首页 > 解决方案 > const ref 传递的模板化参数是否优化为在足够小的时候按值传递?

问题描述

当一个标准函数接受一个模板化的参数而不修改它时,它似乎总是接受一个const ref(例如:std::vector::insert)。

这是否意味着参数之类的bool函数将变为std::vector<bool>::insert(const bool& value)

或者是否有一些优化可以std::vector<bool>::insert(bool value)代替它?如果是,我自己的模板函数也会从中受益吗?

标签: c++templatesparameter-passing

解决方案


std::vector是一个模板,因此std::vector<bool>::insert()是根据定义inline

现代编译器很容易“看穿”inline调用中的引用并将它们全部优化。

对于像这样的小对象int,按引用传递和按值传递没有区别。

例子:

struct A {
    int func1(const int& x) { return x + 1; }
    int func2(int y) { return y + 1; }
};

int func1(int x) {
    A a;
    return a.func1(x);
}

int func2(int y) {
    A a;
    return a.func2(y);
}

生成的代码(godbolt链接):

func1(int):                              # @func1(int)
        lea     eax, [rdi + 1]
        ret
func2(int):                              # @func2(int)
        lea     eax, [rdi + 1]
        ret

如果您通过共享库公开 API,通过引用传递可能会导致额外的取消引用。这是因为在 C++ ABI 中,按引用传递实际上是通过指针发生的。但是对于inline电话来说,这通常不是问题。

另一方面,如果复制或使用大对象涉及副作用,则按值传递大对象可能不容易优化。所以对于一个通用模板,通过引用传递是一个聪明的设计选择。


推荐阅读