weird C++ constructor/copy constructor issues in g++

妖精的绣舞 提交于 2019-12-11 10:15:51

问题


#include <iostream>
using namespace std;

class X {
        public:
                X() {
                        cout<<"Cons"<<endl;
                }
                X(const X& x){
                        cout<<"Copy"<<endl;
                }
                void operator=(const X& x){
                        cout<<"Assignment called";
                }
};

X& fun() {
        X s;
        return s;
}

int main(){
        X s = fun();
        return 0;
}

This code calls the copy constructor also. Why does this work? I recall that the first time I ran this program, it seg faulted. But after a while, it started calling this copy cons. and now works!! Wierd.

But if I replace, fun() as follows:

X fun() {
        X s;
        return s;
}

Then copy cons. is not called. I thought that the copy cons. would be called in this case. But as pointed out by @flyfishr64, RVO is coming into play here. But it still does not explain the case where I am returning a reference. I think it should always segfault.

Any explanations?


回答1:


To expand on @flyfishr64's answer

The copy constructor is invoked here because this:

X s = fun();

is an initialization. You are using fun() to construct the object, not invoking the default constructor. It is equivalent to:

X s(fun());

The "Cons" you see printed out is for the instance in fun(). See this article: Assignment operator in C++ for more.




回答2:


This returns reference to an object on stack which does not exist once the method returns - the stack is unwinded, the memory is still there but you should not be using it

X& fun() {
        X s;
        return s;
}

When you change that to:

X fun() {
        X s;
        return s;
}

You are now returning a copy. If the compiler is clever enough it might do:

X fun() {
    return X();
}

In that case the X is allocated directly in the callers stack so that copy is not required.

If it segfault or not depends on if you are accessing invalid memory.

In your example you don't access any values from the structure. To see segfault, first keep a reference that you returned with fun() add some variables into structure X and after return from fun() call another method that internally allocates some memory on stack (this should overwrite the original memory used by X in fun) and stores some values on stack (preferable 0's). After this second method returns try to print out values from the X using the original reference returned from fun ...




回答3:


In this code:

X fun() {
        X s;
        return s;
}

the copy constructor isn't getting called because of the Return Value Optimization which allows the compiler to bypass creating the local variable 's' and construct X directly in the returned variable.

You can read more about RVO here




回答4:


When you return a reference to a local variable like that, you're invoking undefinied behaviour.

It happens to work in this case because none of the functions of class X actually use the this pointer, so it doesn't matter that it's no longer valid.



来源:https://stackoverflow.com/questions/1806711/weird-c-constructor-copy-constructor-issues-in-g

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!