вернуть объект, созданный в функции.разница Mingw и Cl - PullRequest
0 голосов
/ 08 июня 2018

У меня следующий код:

#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

Это ожидаемый результат для меня, программируя только с wingw и g++ Но когда япытался использовать Microsoft cl Я получил это: constructor: 00000000001BF750 foo: 00000000001BF750 destructor: 00000000001BF750 destructor: 00000000001BF790

Два вызова деструктора?Только один вызов конструктора?Хорошо, foo создайте свой собственный объект и вызовите copy конструктор для return.Но зачем мне его копировать, когда компилятор может поместить объект в main стек функций, например, mingw, и поставить указатель 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 ссылками?

1 Ответ

0 голосов
/ 08 июня 2018

Конструкторы - не единственный способ создания объекта.A Copy Constructor и Move Constructor (C ++ 11 и далее) могут делать то же самое.

В вашем случае, когда выполняется return ex, экземпляр, созданный в функции, удаляется, и новый экземплярсоздается с помощью Copy Constructor.вы получите распечатку, если напишите следующий код

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

Копирование произойдет до уничтожения исходного объекта, и, следовательно, вы увидите эту распечатку перед деструктором.

Почему этого не происходитв некоторых компиляторах?

Из-за механизма, называемого RVO (оптимизация возвращаемого значения), компилятор понимает, что вы будете использовать один и тот же экземпляр, и поэтому он перемещается, а не копируется.

Надеюсь, что это проясняет.

...