return 在函数中创建的对象。 mingw和cl的区别

return object created in function. mingw and cl difference

我有下一个代码:

#include <iostream>

class Example
{
public:
    Example()
    {
        std::cout
            << "constructor: "
            << std::hex
            << this
            << std::endl;
    }

    ~Example()
    {
        std::cout
            << "destructor:  "
            << std::hex
            << this
            << std::endl;
    }

    static Example foo()
    {
        Example ex;

        std::cout
            << "foo:         "
            << std::hex
            << &ex
            << std::endl;

        return ex;
    }
};


int
main()
{
    Example ex = Example::foo();
}

Mingw编译程序说: constructor: 0x22fe4f foo: 0x22fe4f destructor: 0x22fe4f

这是我仅使用 wingwg++ 编程的预期结果 但是当我尝试使用 Microsoft cl 时,我得到了这个: constructor: 00000000001BF750 foo: 00000000001BF750 destructor: 00000000001BF750 destructor: 00000000001BF790

两次析构函数调用?只有一个构造函数调用?好的,foo 创建它自己的对象并在 return 上调用 copy 构造函数。但是,当编译器可以像 mingw 一样将对象放入 main 函数堆栈并将 out 指针作为参数单独放入 foo 函数时,为什么我需要复制它? 像这样:

    // no return but `out` reference
    static void foo(Example &ex)
    {
        std::cout
            << "foo:         "
            << std::hex
            << &ex
            << std::endl;
    }
};


int
main()
{
    Example ex; // allocate memory in stack
    Example::foo(ex); // process/fill it
}

我做错了什么或者有什么方法可以不调用 copy 构造函数并且不使用 out 引用编写代码?

构造函数不是创建对象的唯一方法。 Copy ConstructorMove Constructor(C++11 之后)可以做同样的事情。

在您的例子中,当执行 return ex 时,函数中创建的实例将被删除,并使用 Copy Constructor 创建一个新实例。如果您编写以下代码,您将获得印刷品

Example(const Example &) {
        std::cout << "Copy Constructor" << std::hex << this << std::endl;
    }

复制发生在原始对象销毁之前,因此您会在析构函数之前看到此打印。

为什么它不会在某些编译器中发生?

由于称为 RVO(Return 值优化)的机制,编译器会智能地理解您将使用相同的实例,因此它被移动而不是被复制。

希望它澄清。