1

如果有一个函数不接受任何引用或指针作为参数,它的返回类型是未使用的,并且它不进行明显离开系统的调用(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不必是相同的大小,但是如果它们被定义为相同的大小,这是否必须工作,或者它仍然是未定义的行为?

目的是看一个函数是否可以合法地优化出来(即如果你能证明它没有副作用,它可以被删除)。

4

2 回答 2

1

该标准保证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);

允许编译器删除没有副作用的代码,但仅通过检查函数签名无法明确确定。对于内联函数,编译器可以看到代码,编译器就有机会。对于在不同翻译单元中定义的函数,事情有点困难(通过链接时间优化,如果函数足够小,它仍然是可行的)。

请注意,这不仅限于通过值或常量引用获取参数的函数。如果编译器看到一个函数通过引用修改了一个参数,但它可以证明被修改的对象的值再也不会被读取,它理论上可以删除该调用。另一方面,除了简单的情况外,我不会打赌编译器会这样做。

于 2013-04-10T04:10:54.763 回答
0

我想说这属于“定义明确的未定义行为”领域;它可能会一直工作(假设 sizeof(int*) == sizeof(int)),但它在技术上是未定义的,并且某些编译器将来很有可能完全破坏它。另一个例子是使用联合将浮点数重新解释为 int。

另外,如果我没有向您指出 LLVM 的链接时间优化的方向,那我就完全不对劲了。它旨在完全按照您在链接时谈论的内容。它很棒,并且在 osx 上“开箱即用”。他们也有一个很好的简单例子来说明它是如何工作的:http: //llvm.org/docs/LinkTimeOptimization.html

于 2013-04-10T00:38:14.693 回答