我知道,出于可读性原因,在通过引用或指针传递参数时,应该尽可能使用const关键字.如果我指定一个参数为常量,编译器是否可以进行任何优化?

可能有几种情况:

Function parameters:

恒定参考:

void foo(const SomeClass& obj)

常量类对象:

void foo(const SomeClass* pObj)

和指向某个类的常量指针:

void foo(SomeClass* const pObj)

Variable declarations:

const int i = 1234

Function declarations:

const char* foo()

每种编译器都提供了什么样的优化(如果有的话)?

推荐答案

100

Case - 1:

在程序中声明常量时,

int const x = 2;

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

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

const int x = 1;
const int* y = &x;

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

就函数参数而言,const表示函数中不修改参数.据我所知,使用const并没有显著的性能提升,而是一种确保正确性的方法.


Case - 2:

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

const Y& f( const X& x )
{
    // ... do something with x and find a Y object ...
    return someY;
}

编译器能做得更好的是什么?它能避免参数或返回值的副本吗?

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

它能将x或某物的副本放入只读存储器吗?

不,因为xsomeY都生活在它的范围之外,都来自和/或给予了外部世界.即使someY本身在飞翔上是动态分配的,它和它的所有权也会让给调用者.

对出现在f()主体内的代码进行可能的优化怎么办?由于const,编译器能以某种方式改进它为f()主体生成的代码吗?

即使在调用常量成员函数时,编译器也不能假定对象x或对象someY的位不会改变.此外,还有其他问题(除非编译器执行全局优化):编译器可能也不确定其他代码是否具有将同一对象别名为x和/或someY的非常量引用,而且,在f();的执行过程中,对同一对象的任何此类非常量引用是否会被意外使用,编译器甚至可能不知道xsomeY仅仅是引用的真实对象是否首先被声明为常量.


Case - 3:

void f( const Z z )
{
    // ...
}

这里面会有什么优化吗?

是的,因为编译器知道z确实是一个常量对象,所以即使没有全局分析,它也可以执行一些有用的优化.例如,如果f()的主体包含像g( &z )这样的调用,那么编译器可以确保z的不可变部分在对g()的调用期间不会改变.

C++相关问答推荐

如何用C(使用两个s补数算术的32位程序)计算

如何确保内存分配在地址附近?

我可以动态分配具有空类型函数的矩阵吗?

gcc已编译的可执行文件TSB是否同时暗示最低有效字节和最低有效位?

DPDK-DumpCap不捕获端口上的传入数据包

是否所有C编译器在将浮点数转换为整型数时都会隐式删除小数?

仅在给定的大小和对齐方式下正确创建全局

为什么即使在强制转换时,此代码也会溢出?

自定义变参数函数的C预处置宏和警告 suppress ?

在WSL关闭/重新启动后,是什么原因导致共享对象依赖关系发生更改?

如何按顺序将所有CSV文件数据读入 struct 数组?

如何编写一个for循环来计算C中各项的总和?

==284==错误:AddressSaniizer:堆栈缓冲区下溢

发送和接收的消息中的Unix域套接字不匹配

共享目标代码似乎不能在Linux上的进程之间共享

如何使crc32的结果与cksum匹配?

macos/arm64 上地址空间不使用第一位吗?

GnuCobol 使用 double 类型的参数调用 C 函数

使用共享变量同步多线程 C 中的函数

当 a 是代码块时使用逗号运算符 (a, b)