Следующий код корректно компилируется с Visual Studio 2013:Почему для конструктора по умолчанию требуется дефолт по умолчанию для класса, используемого в unique_ptr?
#include <memory>
namespace NS
{
class SomeOtherClass;
class MyClass
{
public:
MyClass();
virtual ~MyClass();
private:
std::unique_ptr<SomeOtherClass> m_someOtherClass;
};
}
int main()
{
auto mc = NS::MyClass();
}
Это происходит из-за ошибки в Visual Studio 2013, в котором инициализация mc
в main
непосредственно оптимизированной без проверки конструктора перемещения.
В Visual Studio 2015 это не компилируется, так как конструктор шаг должен существовать, поэтому мы изменим код так:
#include <memory>
namespace NS
{
class SomeOtherClass;
class MyClass
{
public:
MyClass();
virtual ~MyClass();
MyClass(MyClass&&) = default;
private:
std::unique_ptr<SomeOtherClass> m_someOtherClass;
};
}
int main()
{
auto mc = NS::MyClass();
}
И снова это компилирует.
Но если мы хотим экспортировать DLL, то компиляция снова завершится неудачно. Это модифицированный код:
#include <memory>
namespace NS
{
class SomeOtherClass;
class __declspec(dllexport) MyClass
{
public:
MyClass();
virtual ~MyClass();
MyClass(MyClass&&) = default;
private:
std::unique_ptr<SomeOtherClass> m_someOtherClass;
};
}
int main()
{
auto mc = NS::MyClass();
}
Это часть вывода компилятора:
memory(1193): error C2027: use of undefined type 'NS::SomeOtherClass'
test.cpp(5): note: see declaration of 'NS::SomeOtherClass'
...
memory(1194): error C2338: can't delete an incomplete type
memory(1195): warning C4150: deletion of pointer to incomplete type 'NS::SomeOtherClass'; no destructor called
Кажется, что по умолчанию сгенерированного шага-конструктор по требует быть в состоянии уничтожить SomeOtherClass
. Это странно, потому что MyClass
имеет деструктор, в котором известно полное определение SomeOtherClass
.
Так почему же эта компиляция при экспорте DLL? И почему конструктор перемещения по умолчанию требует знания определения SomeOtherClass
?
Я не могу сказать, почему (хороший вопрос, хотя). вы можете исправить это, когда у вас есть MyClass :: MyClass (MyClass &&) = default; 'в вашем файле cpp и только объявление в файле заголовка. – Hayt
Не можете ли вы написать 'NS :: MyClass mc;' в 'main()'? – alain