可能对编译器或已定义行为进行优化
Possible optimization for compilers or defined behaviour
如果有一个函数不接受任何引用或指针作为参数,它的返回类型是未使用的,并且它不进行明显离开系统的调用(I/O调用,更改系统时间等),它是否保证只修改定义它的类(或根本不修改)?
我能想到的唯一例外情况如下:
void a(int b, int c){
*((int*)b) = c; }
int main() {
int d=1;
a((int)(&d),d+1);
return 0; }
保证被定义吗?我知道int*
和int
不必是相同的大小,但如果它们被定义为相同的大小,这必须起作用吗,或者它仍然是未定义的行为?
目的是看一个函数是否可以合法地优化出来(即,如果你能证明它没有副作用,它可以被删除)。
标准保证用于从指针转换为合适的整型(大到足以容纳所有值)并返回到原始指针类型的reinterpret_cast
保证产生相同的指针值。是的,这是可以保证的:
int *p = new int(5);
intptr_t i = reinterpret_cast<intptr_t>(p);
// ...
int *q = reinterpret_cast<int*>(i);
assert(p == q);
*q = 10;
assert(*p == 5);
编译器允许删除没有副作用的代码,但不能通过检查函数签名来清楚地确定。对于内联函数,编译器对代码具有可见性,编译器有机会。对于在不同的翻译单元中定义的函数来说,事情有点困难(如果函数足够小,那么使用链接时间优化仍然是可行的)。
请注意,这不仅限于通过值或const引用接受实参的函数。如果编译器看到一个函数通过引用修改了的实参,但它可以证明修改后的对象的值永远不会再被读取,那么理论上它可以删除该调用。另一方面,除了简单的情况,我不会打赌编译器会这样做。
我认为这属于"定义良好的未定义行为";它可能会一直工作(假设sizeof(int*) == sizeof(int)),但它在技术上是未定义的,并且将来某些编译器可能会完全破坏它。另一个例子是使用联合将浮点数的位重新解释为int型。
另外,如果我没有指出LLVM的链接时间优化方向,那我就大错特错了。它的目的是做你在链接时谈论的事情。它很棒,在osx上"开箱即用"。他们也有一个很好的简单的例子来说明它是如何工作的:http://llvm.org/docs/LinkTimeOptimization.html
- FBString 的小字符串优化是否依赖于未定义的行为?
- 未优化的 constexpr 的未定义引用用作默认参数
- 未定义的行为或 gcc 优化错误
- 未定义的行为确实有助于现代编译器优化生成的代码
- 如何告诉编译器不要在 /ob1 优化下内联在类定义中定义的方法
- 通过宏定义编译标志(C++11 和优化)
- 对于这种自定义MD5比较,可以进行哪些优化
- c++链接器错误:未定义的引用仅在优化的生成上
- 定义新的优化类型
- 这种编译器优化不一致是否完全由未定义的行为来解释
- 编译器如何优化不正确C++分层向下转换以导致真正的未定义行为
- `std::string`分配是我当前的瓶颈-如何使用自定义分配器进行优化
- 来自优化级别的C++多定义链接器错误
- 在CMake项目中编译后增加自定义llvm优化命令(opt)
- 如果没有定义Move语义(Move构造函数和Move赋值操作符),编译器是否默认优化
- 可能对编译器或已定义行为进行优化
- c++自定义类型向量优化
- 利用简短且定义可用的虚拟方法进行优化
- G++ 4.9 上静态 constexpr 的未定义引用,没有优化
- 为什么 gcc 使用我的自定义迭代器优化这个 C++11 foreach 循环