奇怪的 C++ g++ 中的构造函数/复制构造函数问题

发布于 2024-08-12 19:48:10 字数 832 浏览 6 评论 0原文

#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;
}

此代码还调用复制构造函数。为什么这有效?我记得我第一次运行这个程序时,它出现了段错误。但过了一段时间,它开始称此为复制骗局。现在可以了!!奇怪。

但如果我替换 fun() 如下:

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

然后复制 cons.不被调用。我认为复制的缺点。在这种情况下会被调用。但正如 @flyfishr64 所指出的,RVO 在这里发挥了作用。但它仍然无法解释我返回参考的情况。我认为它应该总是出现段错误。

有什么解释吗?

#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?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

〆凄凉。 2024-08-19 19:48:10

这将返回对堆栈上的对象的引用,该对象在方法返回后不存在 - 堆栈已展开,内存仍然存在,但您不应该使用它

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

当您将其更改为:

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

您现在正在返回一个副本。如果编译器足够聪明,它可能会这样做:

X fun() {
    return X();
}

在这种情况下,X 直接在调用者堆栈中分配,因此不需要复制。

是否出现段错误取决于您是否正在访问无效内存。

在您的示例中,您没有从结构中访问任何值。要查看段错误,首先保留使用 fun() 返回的引用,将一些变量添加到结构 X 中,然后从 fun() 调用返回后另一种方法在堆栈上内部分配一些内存(这应该覆盖 fun 中的 X 使用的原始内存)并在堆栈上存储一些值(最好是 0)。在第二个方法返回后,尝试使用从 fun 返回的原始引用从 X 打印出值...

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 ...

恍梦境° 2024-08-19 19:48:10

扩展 @flyfishr64 的答案

复制构造函数在这里被调用,因为 this:

X s = fun();

是一个初始化。您正在使用 fun() 来构造对象,而不是调用默认构造函数。它相当于:

X s(fun());

您看到打印出来的“缺点”是针对 fun() 中的实例的。请参阅这篇文章:C++ 中的赋值运算符了解更多信息。

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.

暖伴 2024-08-19 19:48:10

在此代码中:

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

由于返回值优化,复制构造函数不会被调用,它允许编译器绕过创建局部变量 's' 并直接在返回的变量中构造 X。

您可以此处了解有关 RVO 的更多信息

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

血之狂魔 2024-08-19 19:48:10

当您返回对这样的局部变量的引用时,您正在调用未定义的行为。

它恰好在这种情况下起作用,因为 class X 的任何函数都没有实际使用 this 指针,因此它不再有效并不重要。

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文