C ++传递指针/常量。效率

时间:2015-10-08 22:13:56

标签: c++

我正在和一个做很多计算的朋友一起开展项目,我们正在使用c ++。我有一段时间没用过c ++,他建议修改一下。我希望我可以来这里进行更深入的解释,也许可以与更多的文章联系起来。

他说它更有效而不是拥有这个

Hand::Hand(Card one, Card two)

要有这个

Hand::Hand(const Card &one, const Card &two)

这是对的吗?传递一个常量地址而不是对象本身会使它更有效率呢?他提到传递参考而不是制作副本。如果我不通过地址,它会构建一个新的卡片对象作为我通过的那个的副本吗?

另外

而不是

bool Hand::hasFourKind(Card board[])

有这个

 bool Hand::hasFourKind(const Card *board)

这会将指针传递给数组的开头而不是制作数组副本吗?

3 个答案:

答案 0 :(得分:0)

在大多数情况下,如果您不需要修改局部变量,则第一个示例的后一个方法更快,因为整个对象不必在堆栈上复制以供函数使用它。相反,指针将被推入堆栈,这将花费更少的时间。 (虽然有些调用约定允许在寄存器中传递小参数,但速度更快。)

对于小型对象,复制所花费的时间可能不是问题,但对于大型类/结构可能更明显。

第二个示例具有相同的操作(忽略const ness),因为在任何情况下数组都不会通过值传递。它将作为简单指针传递,或通过“引用”传递。

答案 1 :(得分:0)

从优化的角度来看,编译器不能依赖const实际上意味着“不会改变”。 const_cast允许函数改变某些东西的常数,以便可以改变它。程序员知道“如果我不小心修改了这个错误,我会收到错误”(特别是错误标记if (a = b)而不是if (a == b))是很有用的。

如果编译器可以使用函数的源代码,那么无论是否将其标记为const,它本身都可以证明某个值没有被更改或正在被更改。

在与Chandler Carruth(Clang和LLVM目前最活跃的开发者之一)的视频中,他实际上推动对任何类型相当小的类型使用非引用调用。通常,编译器会优化掉参数的副本,因为可以修改引用[所以如果编译器没有可用的源代码,它将不知道值是否被更改]

无论您使用Card board[]还是Card *board都不会改变,编译器将以任何一种方式生成完全相同的代码 - 如果您希望其他人阅读代码以了解该函数是否需要修改是否为值,然后为未更改的值添加const

答案 2 :(得分:0)

Hand::Hand(const Card &one, const Card &two)

比这个

更有效率
Hand::Hand(Card one, Card two)

有两个原因

  1. 它避免复制Cards
  2. 如果您想维护一张卡片组,可能会使用第一种方法,但由于我的第一点所解释的原因而无法使用第二种方法
  3. bool Hand::hasFourKind(Card board[])
    

    等同于此

    bool Hand::hasFourKind(const Card *board)
    

    因为它们都代表卡片阵列,但第一个只是用于指向卡片的合成糖,因此它们实际上都代表了指向卡片的指针。

    第二个更好,因为它意味着董事会不能被其他任何人修改。由于const_cast可以用来移除对象的constness,因此这并不是一个很好的防范。 如果您真的想确保该方法中的任何人都无法修改卡片,那么我建议您稍微更改设计以启用此功能:

    bool Hand::hasFourKind() const;
    

    卡片是Hand课程的一部分,任何人都无法修改