C++ 通过const ref传递整数类型有什么好处

C++ 通过const ref传递整数类型有什么好处,c++,reference,C++,Reference,问题是:通过常量引用传递整型是否比通过值传递整型有好处 即 vs 对于用户定义的类型,答案是明确的,case#1避免了不必要的复制,同时确保了对象的常量。但是在上面的例子中,引用和整数(至少在我的系统上)是相同的大小,所以我无法想象函数调用所需的时间(由于复制)会有很大的不同。但是,我的问题实际上与函数内联的编译器有关: 对于非常小的内联函数,编译器是否必须在第2种情况下复制整数?通过让编译器知道我们不会更改引用,它可以内联函数调用而不必复制整数吗 欢迎任何建议。通常不值得。即使对于内联函数,编

问题是:通过常量引用传递整型是否比通过值传递整型有好处

vs

对于用户定义的类型,答案是明确的,case#1避免了不必要的复制,同时确保了对象的常量。但是在上面的例子中,引用和整数(至少在我的系统上)是相同的大小,所以我无法想象函数调用所需的时间(由于复制)会有很大的不同。但是,我的问题实际上与函数内联的编译器有关:

对于非常小的内联函数,编译器是否必须在第2种情况下复制整数?通过让编译器知道我们不会更改引用,它可以内联函数调用而不必复制整数吗


欢迎任何建议。

通常不值得。即使对于内联函数,编译器也不会愚蠢。唯一一次我会说它是合适的是如果你有一个模板;仅仅为了复制而不是参考而专门开发内置软件可能不值得付出额外的努力。

我想不出有什么好处。我甚至看到过这样的建议,即在编写模板时,使用元编程按值传递整数类型,并且只对非整数类型使用常量引用。

当有人对基本数据类型使用这样的常量引用时,我实际上觉得很恼火。我看不出这样做有什么好处,尽管有人认为对于大于
sizeof(指针)
的数据类型,这样做可能更有效。虽然,我真的不关心这种微小的“优化”。

引用的成本通常与整数类型的成本相同,但对于引用,必须进行间接寻址,因为对某些内存的引用必须解析为值


只需按值复制,对内置类型坚持不变的约定。

这取决于编译器,但我希望任何合理的优化器都会以任何方式为您提供相同的结果

我用gcc进行了测试,结果确实是一样的。以下是我测试的代码:

inline int foo(const int& n) {
  return n * 2;
}

int bar(int x) {
  int y = foo(x);
  return y;
}
(带和不带const&on foo的n参数)

然后,我使用gcc 4.0.1和以下命令行进行编译:

g++ -O3 -S -o foo.s foo.cc

这两个编译器的输出是相同的。

通过const ref传递一个内置的int类型实际上是一个较小的去优化(通常)。至少对于非内联函数。编译器可能必须实际传递一个指针,该指针必须被反引用才能获得值。您可能认为它总是可以优化这一点,但别名规则和支持单独编译的需要可能会迫使编译器采取行动

但是,关于第二个问题:

对于非常小的内联函数,编译器是否必须在第2种情况下复制整数?通过让编译器知道我们不会更改引用,它可以内联函数调用而不必复制整数吗


如果语义允许的话,编译器应该能够优化掉副本或取消引用,因为在这种情况下,编译器完全了解调用站点的状态和函数实现。它可能只是按照自己的方式将值加载到寄存器中,并在处理完参数后将寄存器用于其他用途。当然,所有这些都取决于函数的实际实现。

不要这样做
int
与普通32位平台上的指针/引用大小相同,而在64位平台上的指针/引用则更小,因此您可能会在性能上处于劣势而不是优势。我的意思是,所有函数参数都按顺序推送到堆栈上,以便函数可以读取它们,它要么是您的int,要么是引用时的地址。另一个缺点是被调用方要么通过间接方式(取消引用地址)访问您的
n
,要么在堆栈上进行复制作为优化

如果对按值传递的int进行了一些更改,则可能会将其写回堆栈上传递它的位置,或者写回新的堆栈位置。第二种情况自然不是有利的,但不应该发生。通过便秘,你可以阻止自己做出这样的改变,但这对
const int
也同样有效


当然,在正确的内联情况下,这并不重要,但请记住,并不是所有内联编写的内容都是这样的。

在编写或使用模板时,您可能会得到(const int&),因为模板编写器不知道实际的类型。如果对象是重量级的,传递引用是正确的做法;如果它是一个int或什么的,编译器可能能够优化它了


在缺乏某种外部需求的情况下,通常没有理由对一次性函数执行类似操作——这只是额外的键入,再加上到处抛出引用实际上会抑制优化。在寄存器中复制小数据比从内存中重新加载要便宜得多,以防发生更改

很多人都说这两者没有区别。我可以看到一个(也许是人为的)案例,在这个案例中,差异会很重要

int i = 0;

void f(const int &j)
{
    i++;

    if (j == 0)
    {        
        // Do something.
    }
}

void g()
{
    f(i);
}
但是。。正如其他人所提到的。。。整数和指针的大小可能相似。对于像整数这样小的对象,引用会降低性能。除非经常调用您的方法,否则它可能不会太引人注目,但它会在那里。另一方面,在某些情况下,编译器可能会对其进行优化。

这不仅仅是性能问题。 一个真实的故事:本周我注意到一位同事试图改进数字配方,并替换了宏


    #define SHFT(a,b,c,d) do { (a)=(b); (b)=(c); (c)=(d); } while (0)
通过这个函数


    inline void Rotate(double& dFirst, double& dSecond, double& dThird, const double dNewValue)
    {
        dFirst = dSecond;
        dSecond = dThird;
        dThird = dNewValue;
    }   // Function Rotate
如果他通过引用传递了最后一个参数,那么这可能会起作用,但实际上,这段代码


        Rotate(dum,*fb,*fa,dum);
w

    inline void Rotate(double& dFirst, double& dSecond, double& dThird, const double dNewValue)
    {
        dFirst = dSecond;
        dSecond = dThird;
        dThird = dNewValue;
    }   // Function Rotate

        Rotate(dum,*fb,*fa,dum);