const 在 C/C++ 中提供什么样的优化?
我知道,出于可读性原因,您应该在通过引用或指针传递参数时尽可能使用 const 关键字.如果我指定一个参数是常量,编译器是否可以做任何优化?
可能有几种情况:
功能参数:
常量引用:
void foo(const SomeClass& obj)
常量 SomeClass 对象:
void foo(const SomeClass* pObj)
还有指向 SomeClass 的常量指针:
void foo(SomeClass* const pObj)
变量声明:
const int i = 1234
函数声明:
const char* foo()
每个都提供什么样的编译器优化(如果有的话)?
解决方案来源
案例 - 1:
当你在你的程序中声明一个常量时,
int const x = 2;
编译器可以通过不向该变量提供存储而将其添加到符号表中来优化此常量.因此,后续读取只需要间接到符号表中,而不是从内存中获取值的指令.
注意:如果您执行以下操作:
const int x = 1;常量 int* y = &x;
那么这将强制编译器为 x
分配空间.因此,对于这种情况,这种程度的优化是不可能的.
对于函数参数而言,const
表示函数中不修改参数.据我所知,使用 const
并没有显着的性能提升,而是一种确保正确性的方法.
案例 - 2:
<块引用>将参数和/或返回值声明为 const 是否有助于编译器生成更优化的代码?"
const Y&f( 常量 X& x ){//... 对 x 做一些事情并找到一个 Y 对象 ...返回一些Y;}
<块引用>
编译器在哪些方面可以做得更好?是否可以避免参数或返回值的副本?
不,因为参数已经通过引用传递.
<块引用>它可以将 x 或 someY 的副本放入只读内存吗?
不,因为 x
和 someY
都存在于其范围之外,并且来自和/或被给予外部世界.即使 someY
是在 f()
本身内动态分配的,它和它的所有权都交给调用者.
出现在 f() 主体中的代码可能会进行哪些优化?由于 const,编译器能否以某种方式改进它为 f() 的主体生成的代码?
即使调用 const 成员函数,编译器也不能假定对象 x
或对象 someY
的位不会改变.此外,还有其他问题(除非编译器执行全局优化):编译器也可能不确定没有其他代码可能有一个非常量引用,该引用将同一对象与 x
和/或 someY
,以及在执行 f();
期间是否会偶然使用对同一对象的任何此类非 const 引用,编译器甚至可能不知道x
和 someY
只是引用的真实对象,实际上首先声明为 const.
案例 - 3:
void f( const Z z ){//...}
<块引用>
这里面会有优化吗?
是的,因为编译器知道 z
确实是一个 const 对象,即使没有全局分析,它也可以执行一些有用的优化.例如,如果 f()
的主体包含像 g( &z )
这样的调用,编译器可以确定 的非可变部分z
在调用 g()
期间不要更改.
I know that where possible you should use the const keyword when passing parameters around by reference or by pointer for readability reasons. Is there any optimizations that the compiler can do if I specify that an argument is constant?
There could be a few cases:
Function parameters:
Constant reference:
void foo(const SomeClass& obj)
Constant SomeClass object:
void foo(const SomeClass* pObj)
And constant pointer to SomeClass:
void foo(SomeClass* const pObj)
Variable declarations:
const int i = 1234
Function declarations:
const char* foo()
What kind of compiler optimizations each one offers (if any)?
解决方案Source
Case - 1:
When you declare a const in your program,
int const x = 2;
Compiler can optimize away this const by not providing storage to this variable rather add it in symbol table. So, subsequent read just need indirection into the symbol table rather than instructions to fetch value from memory.
Note: If you do something like:
const int x = 1;
const int* y = &x;
Then this would force compiler to allocate space for x
. So, that degree of optimization is not possible for this case.
In terms of function parameters const
means that parameter is not modified in the function. As far as I know, there's no substantial performance gain for using const
rather it's a means to ensure correctness.
Case - 2:
"Does declaring the parameter and/or the return value as const help the compiler to generate more optimal code?"
const Y& f( const X& x )
{
// ... do something with x and find a Y object ...
return someY;
}
What could the compiler do better? Could it avoid a copy of the parameter or the return value?
No, as argument is already passed by reference.
Could it put a copy of x or someY into read-only memory?
No, as both x
and someY
live outside its scope and come from and/or are given to the outside world. Even if someY
is dynamically allocated on the fly within f()
itself, it and its ownership are given up to the caller.
What about possible optimizations of code that appears inside the body of f()? Because of the const, could the compiler somehow improve the code it generates for the body of f()?
Even when you call a const member function, the compiler can't assume that the bits of object x
or object someY
won't be changed. Further, there are additional problems (unless the compiler performs global optimization): The compiler also may not know for sure that no other code might have a non-const reference that aliases the same object as x
and/or someY
, and whether any such non-const references to the same object might get used incidentally during the execution of f();
and the compiler may not even know whether the real objects, to which x
and someY
are merely references, were actually declared const in the first place.
Case - 3:
void f( const Z z )
{
// ...
}
Will there be any optimization in this?
Yes because the compiler knows that z
truly is a const object, it could perform some useful optimizations even without global analysis. For example, if the body of f()
contains a call like g( &z )
, the compiler can be sure that the non-mutable parts of z
do not change during the call to g()
.
相关文章