【问题标题】:Inline Function Arguments Passing内联函数参数传递
【发布时间】:2011-11-29 09:50:06
【问题描述】:

内联函数是否需要性能来通过const引用

foo(const T & a, const T &b)

按价值比较

foo(T a, T b)

如果我不改变函数中 a 和 b 的值? C++11 的变化是否推荐了这里的任何具体内容?

【问题讨论】:

  • 值是值,引用是引用。传递一个 const 引用而不是传递一个值是一个错误,可能会严重反击。见stackoverflow.com/questions/4705593/int-vs-const-int/…
  • @6502:这是使用引用使逻辑更加复杂的一个很好的例子(v.push_back(v[0]) 是合法的,因为标准库必须包含额外的逻辑)。
  • @BenVoigt:很高兴看到此请求已添加到标准中。哪里写的?
  • @6502:如果在调用push_back 时引用有效,则标准库有责任对其进行正确处理。
  • @BenVoigt:对不起,我不同意。在调用传递引用的函数时,如果被引用的对象在函数的持续时间内没有足够长的时间,这是一个调用者问题(被调用者无法控制它)。 AFAIK 标准并没有说复制操作必须在释放之前完成:如果一个实现想要这样做就可以了,但是一个有效的 C++ 编译器可以让守护进程飞离我的鼻子仍然保持兼容。顺便说一句,现在使用 C++0x 事情变得更加复杂了……重新分配可以使用移动构造函数吗?如果是这样,仅仅延迟销毁旧存储是不够的......

标签: c++ performance c++11 const-reference


【解决方案1】:

如果参数是临时的,按值传递只能省略复制构造函数调用。

当函数被内联时,通过 const 引用传递原始类型将没有成本。但是通过值传递一个复杂的左值将强加一个潜在的昂贵的复制构造函数调用。所以更喜欢通过 const 引用传递(如果别名不是问题的话)。

【讨论】:

  • 除了别名问题还有生命周期问题。
  • @6502:在返回值上,肯定的。对于参数,可能会出现生命周期问题,但它们非常罕见。无论如何,我会认为它们是混叠问题的一个子集。
  • @BenVoigt Passing primitive types by const reference will have no cost when the function is inlined. 你的意思是“在成本方面没有任何好处”吗?当函数被内联时,您能否确认通过const int&const int 是否有任何好处?
  • @Antonio:不,我是认真的。一般来说,通过const 引用传递会有很大的成本:除了实际数据之外,被调用者还必须访问一个指针,这意味着两次内存访问。被调用者还必须担心混叠,这会抑制一些优化。当函数被内联时,编译器可以确定别名是否实际上是可能的,并且通常可以进行这些优化并直接访问数据,而不是通过额外的指针。
【解决方案2】:

理论上,没有引用的那些可能会被复制到内存中,因为您的内联函数可能会修改它们(即使它实际上没有)。

在许多情况下,编译器足够聪明,可以挑选出这种东西,但这取决于编译器和优化设置。此外,如果您的函数调用了类变量中的任何非 const 成员函数,那么您的编译器必须足够聪明才能检查它们是否也在修改任何内容。

通过使用 const 引用,您基本上可以给它一个相当清晰的指示。

编辑:我只是看一下在 ddd 中使用 GCC 4.6 编译的简单 test program 的机器代码。生成的代码看起来是一样的,所以它似乎被优化了。尽管对于其他编译器来说,这仍然是一种很好的做法,如果没有其他任何东西可以清楚地表明代码的意图。也可能存在编译器无法优化的更复杂的情况。

此外,llvm online dissembler demo 也显示在那里生成了相同的位码。如果你关闭优化,没有 const 引用会稍微长一点。
* 1964 字节 - 没有 const 引用(函数/参数上没有其他 const)
* 1960 字节 - 只是没有 const 引用,但有其他 const。
* 1856 字节 - 带有 const 和 const 引用。

【讨论】:

  • 如果内联函数将 a 和 b 传递给另一个函数,则可能无法优化副本。例如,如果内联函数调用非内联函数bar(a),则编译器必须复制,因为 bar 可能会执行 if (&a == &special) ... 并且原始调用者可能已经传递了 special
  • 再试一次,使用非 POD 类型。
  • 成员函数是否声明为const 对优化器无关紧要。 const 正确性对优化器来说是不可见的,它的设计目的只是为了帮助程序员(如果你违反了 const 声明,就会给出编译时错误),而不是优化器。
  • @6502: const-correctness 在某些情况下确实会影响优化,尽管我同意成员函数的 constness 不是其中之一。
  • @Ben Voigt:可以影响优化的是 const 。引用的常量(如const X &)或指针的常量(如const X *)对优化器从来没有帮助,因为它是一个声明,没有说明被引用或指向的对象的常量(这些声明仅确定指针/引用上的哪些操作有效)。
【解决方案3】:

根据数据类型,按引用传递比按值传递更快。
然而,对于内联函数,函数体(以及因此所有引用/传入的值)被添加到它们无论如何都使用的代码行中,因此从技术上讲,没有变量被传递,只有更多的代码行在同一区域。

参考http://www.cprogramming.com/tutorial/lesson13.html

问题should-i-take-arguments-to-inline-functions-by-reference-or-value下也有非常有帮助的答案

  • 示例可能具有误导性,已删除 -

【讨论】:

  • 这完全是猜测。
  • 按引用传递比按值传递更快取决于类型。此外,使用引用的代码有额外的要求(正确处理别名),并且可能需要按值传递的本机类型不需要的额外间接。
  • 抱歉,由于某种奇怪的原因,我通过指针与值混合,你是对的,它只是对某些数据类型更快。我也指出你stackoverflow.com/questions/722257/… 支持我的观点
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-07-30
  • 2012-01-04
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多