为了账号安全,请及时绑定邮箱和手机立即绑定

const在C / C ++中提供什么样的优化?

const在C / C ++中提供什么样的优化?

C++ C
潇潇雨雨 2019-11-18 12:54:49
我知道,出于可读性原因,在通过引用或指针传递参数时,应尽可能使用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()每个人提供什么样的编译器优化(如果有)?
查看完整描述

3 回答

?
HUH函数

TA贡献1836条经验 获得超4个赞

情况1:-


当您在程序中声明const时,


int const x = 2;

编译器可以通过不为该变量提供存储,而是将其添加到符号表中来优化此const。因此,后续读取仅需要间接进入符号表,而不是从内存中获取值的指令。


注意:-如果您执行以下操作:-


const int x = 1;

const int* y = &x;

然后,这将迫使编译器为分配空间'x'。因此,这种情况下的优化程度是不可能的。


就功能而言,参数const表示未在函数中修改参数。据我所知,使用const它并不会带来实质性的性能提升,而是确保正确性的一种手段。


案例_2:-


“将参数和/或返回值声明为const是否有助于编译器生成更多优化代码?”


  const Y& f( const X& x )

  {

    // ... do something with x and find a Y object ...

    return someY;

  }

Ques =>编译器可以做得更好吗?


=>是否可以避免复制参数或返回值?


否,因为参数已通过引用传递。


=>可以将x或someY的副本放入只读内存吗?


否,因为x和someY都超出其范围,并且来自和/或提供给外部世界。即使someY在f()本身内部动态地动态分配,它和它的所有权也由调用者放弃。


Ques =>关于出现在f()主体内部的代码的可能的优化呢?由于使用了const,编译器能否以某种方式改进它为f()主体生成的代码?


即使您调用const成员函数,编译器也无法假定对象x或对象someY的位不会更改。此外,还有其他问题(除非编译器执行全局优化):编译器也可能不确定是否其他代码可能没有非常量引用来别名相同的对象作为x和/或someY,以及是否存在此类引用。在执行f()时,可能会偶然使用对同一对象的非const引用;并且编译器甚至可能根本不知道x和someY仅仅是引用的实际对象是否实际上首先声明为const。


案例3:


  void f( const Z z )

  {

    // ...

  }

Ques =>会不会有任何优化?


是的,因为编译器知道z确实是一个const对象,所以即使没有全局分析它也可以执行一些有用的优化。例如,如果f()的主体包含类似g(&z)的调用,则编译器可以确保z的不可更改部分在调用g()时不会发生变化。


查看完整回答
反对 回复 2019-11-18
?
狐的传说

TA贡献1804条经验 获得超3个赞

在给出任何答案之前,我想强调指出,const真正使用或不使用的原因应该是为了程序正确性和其他开发人员的清晰度,而不是编译器优化。也就是说,使参数const记录该方法将不会修改该参数,而使成员函数const记录该成员将不会修改该对象是其成员的对象(至少不会以逻辑方式更改任何对象的输出)其他const成员函数)。例如,这样做可以使开发人员避免制作不必要的对象副本(因为他们不必担心原始对象将被破坏或修改)或避免不必要的线程同步(例如,通过知道所有线程仅读取并执行)不会使相关对象发生变异)。


就优化而言,至少在理论上,编译器可以采用优化模式,尽管允许其做出可能破坏标准C ++代码的某些非标准假设,但请考虑以下因素:


for (int i = 0; i < obj.length(); ++i) {

   f(obj);

}

假设该length函数被标记为,const但实际上是一个昂贵的操作(假设它实际上以O(n)时间而不是O(1)时间运行)。如果函数f通过const引用获取其参数,则编译器可能会优化此循环以:


int cached_length = obj.length();

for (int i = 0; i < cached_length; ++i) {

   f(obj);

}

...因为函数f不会修改参数这一事实保证了在length给定对象未更改的情况下,函数每次应返回相同的值。但是,如果f通过可变引用声明要接受参数,length则将需要在循环的每次迭代中重新计算,因为f可能已经修改了对象,从而产生了值的变化。


如评论中所指出的那样,这假设了许多其他警告,并且仅在以非标准模式调用编译器时才可能实现,该模式允许编译器做出其他假设(例如,const方法严格取决于其输入和输出的函数)。优化可以假定代码将永远不会使用const_cast将const引用参数转换为可变引用)。


查看完整回答
反对 回复 2019-11-18
  • 3 回答
  • 0 关注
  • 633 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信