我有一个像这样的C ++类:
class MyClass {
int calculate( int arg1 ) const;
void side_effect( int arg) const;
}
使用方法如下:
{
MyClass m;
m.calculate( 100 );
m.side_effect( 100 );
}
编译器是否可以自由跳过m.calculate( )
调用 - 因为我没有保留返回值?对于side_effect( )
方法,我真的希望编译器不能跳过调用 - 即使方法标记为const
?
编辑:我问这个问题的原因是我的calculate( )
函数有副作用,但通过使用mutable
,它被标记为const
。现在在正常情况下我想要保持返回值,并且整个问题没有实际意义 - 但在上面说明的情况下,我只对确定已经调用副作用感兴趣(是的 - 我知道它不是漂亮 ...)。阅读答案/评论我觉得你认为编译器可以推断一种方法是否有副作用;这让我很惊讶?
答案 0 :(得分:5)
这取决于m.calculate()
的作用。
如果它只检索了值,然后将它们抛弃,那么,确实,你的计算机没有什么用处,你完成的程序可能甚至不能打电话。
但是,编译器可以执行优化的程度受到函数定义的可见性等因素的限制。
const
与此无关。因此,如果m.side_effect()
有副作用,则无法跳过。
答案 1 :(得分:0)
编译将优化掉在运行时没有任何影响的任何代码,如果它可以在编译时告诉它,例如永远不会被调用的分支和从未使用过的值。 Const数据和对象在这里很方便,因为它们的值在编译时是已知的。将const放在一个方法本身上不会改变它:它只是意味着你知道这个方法不会改变它的对象。对象本身仍然是非const的,因此即使该方法是const,编译也不会100%知道该方法运行时的数据值。非const方法仍有可能在某些时候改变了对象。
此外,在类中声明的方法是内联的:它们将被代码本身替换而不是函数调用。无论side_effect方法做什么“动作”都将直接写入代码中代替函数调用本身。整个事情都不会被优化掉,除非它实际上什么都不做,这应该不是问题。
顺便说一句。 const方法仍然可以影响相关对象,例如通过类中的指针访问数据,它可以自由地改变指向的数据,但不能改变指针本身的地址。
答案 2 :(得分:0)
让我们区分'可以和'应该'更加前提。 关于'can',编译器优化某些cetain代码结构的能力取决于代码设计以及编译器的“智能”程度。随着编译器的更多提示,它可以更紧密地优化某些东西。
在您的情况下,如果函数side_effect
和calculate
是虚拟的并且不执行任何操作(并且calculate
返回静态硬编码值),则可以优化它们。除此之外,他们的参数也可以在声明和定义的地方进行优化(请不要将此情况与'should'混合)。但由于这个原因(特别是如果使用了一些简单的编译器),你可能需要提供更多关于参数的提示,将这些参数声明为对int的const引用而不是按值传递它们。
在这种情况下,您的代码
MyClass m;
m.calculate( 100 );
m.side_effect( 100 );
不会为函数或参数生成任何可执行文件的指令。
另外,给出consts,你不会强迫compiller优化一些代码,但是你可以帮助编译器识别代码可以在优化时进行优化。