우선의 코드의 작은 양으로 문제를 재현 할 수 :
#include <memory>
class SomeClass;
int main()
{
std::unique_ptr<SomeClass> ptr;
}
오류 :
In file included from /opt/gcc-explorer/gcc-6.2.0/include/c++/6.2.0/memory:81:0,
from <source>:1:
/opt/gcc-explorer/gcc-6.2.0/include/c++/6.2.0/bits/unique_ptr.h: In instantiation of 'void std::default_delete<_Tp>::operator()(_Tp*) const [with _Tp = SomeClass]':
/opt/gcc-explorer/gcc-6.2.0/include/c++/6.2.0/bits/unique_ptr.h:236:17: required from 'std::unique_ptr<_Tp, _Dp>::~unique_ptr() [with _Tp = SomeClass; _Dp = std::default_delete<SomeClass>]'
<source>:7:30: required from here
/opt/gcc-explorer/gcc-6.2.0/include/c++/6.2.0/bits/unique_ptr.h:74:22: error: invalid application of 'sizeof' to incomplete type 'SomeClass'
static_assert(sizeof(_Tp)>0,
^
Compiler exited with result code 1
같은 문제가 여기 (이 상속과 아무 상관 없다는 것을 증명하기 위해) :
#include <memory>
class SomeClass;
class NotDerived
{
// ~NotDerived(); //defined in cpp
std::unique_ptr<SomeClass> ptr;
};
int main(){
NotDerived d;
}
오류 :
이제210
In file included from /opt/gcc-explorer/gcc-6.2.0/include/c++/6.2.0/memory:81:0,
from <source>:1:
/opt/gcc-explorer/gcc-6.2.0/include/c++/6.2.0/bits/unique_ptr.h: In instantiation of 'void std::default_delete<_Tp>::operator()(_Tp*) const [with _Tp = SomeClass]':
/opt/gcc-explorer/gcc-6.2.0/include/c++/6.2.0/bits/unique_ptr.h:236:17: required from 'std::unique_ptr<_Tp, _Dp>::~unique_ptr() [with _Tp = SomeClass; _Dp = std::default_delete<SomeClass>]'
<source>:5:7: required from here
/opt/gcc-explorer/gcc-6.2.0/include/c++/6.2.0/bits/unique_ptr.h:74:22: error: invalid application of 'sizeof' to incomplete type 'SomeClass'
static_assert(sizeof(_Tp)>0,
^
Compiler exited with result code 1
의이 unique_ptr 정말 기억하자
template<
class T,
class Deleter = std::default_delete<T>
> class unique_ptr;
그리고 default_delete ...
Calls delete
on ptr
그리고 (SomeClass
에) 포인터에 delete
는 Someclass
을 소멸 할 것이다 그렇게 아직 신고하지 않은 SomeClass::~SomeClass
으로 전화해야합니다. 따라서 오류.
왜 관련이 있습니까?
코드에서 Derived
에 대한 소멸자를 선언하지 않으면 기본적으로 ptr
의 소멸자를 호출하는 기본값이 생성됩니다.
이 시점에서 컴파일러는 SomeClass
이라는 완전한 정의가 필요하므로이를 파기하는 방법을 알고 있어야합니다.
Derived에서 소멸자를 선언하면이 문제가 Derived::~Derived
의 imlementation으로 지연됩니다.
[규칙 제로] (http://en.cppreference.com/w/cpp/language/rule_of_three)를 사용하지 않는 이유는 무엇입니까? –
@ 컴파일러 컴파일러 정의 생성자/소멸자는 암시 적으로 인라인되어 헤더에 완전히 알려지기 위해 스마트 포인터에 전달 된 유형을 요구합니다 (전달 선언으로는 충분하지 않습니다). – Resurrection
정말로 좋은 질문입니다. 감사! – Yola