简体   繁体   English

声明 object 并在同一行中调用 function 时发生意外优化

[英]Unexpected optimization happens when declaring object and calling function with it in the same line

I know it is not the best practice writing code like this, but it just happened.我知道编写这样的代码并不是最佳实践,但它就这样发生了。

It is basically about a function like它基本上是关于 function 之类的

C &foo(C &c); // will assign value to c and return c

and a line initializing an object by a self-assignment through the function, like以及通过 function 自分配初始化 object 的行,例如

C c = foo(c);

Here is my simplified code:这是我的简化代码:

class C {
        public:
        C(int i): _i(i) {}
        C(const C& c): _i(c._i){}
        int _i;
};



C &foo(C &c) {
        c = 10;
        return c;
}



int main() {
        C c = foo(c);
        cout << c._i << endl;
        return 0;
}

The function yields different result if compiled with -O3.如果使用 -O3 编译,function 会产生不同的结果。 Without optimization, the result is 10 as expected.如果不进行优化,结果如预期的那样为 10。 With -O3, the result becomes 0. I know gcc must optimize away something, most likely about the constructor of C, but I cannot figure it out.使用 -O3,结果变为 0。我知道 gcc 必须优化一些东西,很可能是关于 C 的构造函数,但我无法弄清楚。

If C is replaced with a primitive type, eg int, then the function yields the same result between optimized and non-optimized code.如果 C 被替换为原始类型,例如 int,则 function 在优化和非优化代码之间产生相同的结果。

This has nothing to do with optimisation;这与优化无关; your program's behaviour is not well-defined.您的程序的行为没有明确定义。 When you change some compiler settings you observe the consequences of that.当您更改某些编译器设置时,您会观察其后果。

When you pass a reference to c into foo , it has not yet been initialised.当您c的引用传递给foo时,它还没有被初始化。 You are allowed to use it but only in limited ways.您可以使用它,但只能以有限的方式使用。 Here you assign a result to it.在这里,您为其分配一个结果。 Then you return the reference again.然后你再次返回参考。 Then it is copy-initialised from itself.然后它从自身复制初始化。 Clearly an initialisation cannot happen after an assignment.显然,在赋值之后不能进行初始化。

Rework your approach.重新设计你的方法。

Why not make it simple?为什么不让它变得简单呢?

C c;
foo(c);

Remember that the "assignment" in the definition is really copy-construction.请记住,定义中的“赋值”实际上是复制构造。 With

C c = foo(c);

what you do is equivalent to你所做的相当于

C c(foo(c));

And the problem here is that when foo(c) is called, the object c haven't been constructed yet, leading to undefined behavior!这里的问题是,当调用foo(c)时,object c尚未构建,导致未定义的行为!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM