我正在和一个做很多计算的朋友一起开展项目,我们正在使用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)
这会将指针传递给数组的开头而不是制作数组副本吗?
答案 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)
有两个原因
Cards
此
bool Hand::hasFourKind(Card board[])
等同于此
bool Hand::hasFourKind(const Card *board)
因为它们都代表卡片阵列,但第一个只是用于指向卡片的合成糖,因此它们实际上都代表了指向卡片的指针。
第二个更好,因为它意味着董事会不能被其他任何人修改。由于const_cast
可以用来移除对象的constness
,因此这并不是一个很好的防范。
如果您真的想确保该方法中的任何人都无法修改卡片,那么我建议您稍微更改设计以启用此功能:
bool Hand::hasFourKind() const;
卡片是Hand
课程的一部分,任何人都无法修改