Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/133.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Pimpl与智能ptr-为什么需要构造函数/析构函数 让我们考虑下面的例子(使用C++ 11)< /P>_C++_C++11_Pimpl Idiom - Fatal编程技术网

Pimpl与智能ptr-为什么需要构造函数/析构函数 让我们考虑下面的例子(使用C++ 11)< /P>

Pimpl与智能ptr-为什么需要构造函数/析构函数 让我们考虑下面的例子(使用C++ 11)< /P>,c++,c++11,pimpl-idiom,C++,C++11,Pimpl Idiom,A.hpp: #include <memory> class A { public: //A(); //~A(); private: struct AImpl; std::unique_ptr<AImpl> pImpl; }; 使用默认构造函数和析构函数。不编译。出现以下错误: 在/usr/include/c++/4.8/memory:81:0中包含的文件中, 从A.hpp:2, 来自main.cpp:2:/usr/includ

A.hpp:

#include <memory>
class A
{
  public:
    //A();
    //~A();

  private:
    struct AImpl;
    std::unique_ptr<AImpl> pImpl;
};
使用默认构造函数和析构函数。不编译。出现以下错误:

在/usr/include/c++/4.8/memory:81:0中包含的文件中, 从A.hpp:2, 来自main.cpp:2:/usr/include/c++/4.8/bits/unique\u ptr.h:在“void”的实例化中 std::default_delete::operator()(_Tp*)const[带_Tp= A::AImpl]':/usr/include/c++/4.8/bits/unique\u ptr.h:184:16:必需 来自'std::unique_ptr::~unique_ptr()[with _Tp=A::AImpl; _Dp=std::default_delete]'A.hpp:3:7:此处需要/usr/include/c++/4.8/bits/unique_ptr.h:65:22:错误:无效 “sizeof”对不完整类型“A::AImpl”的应用
静态断言(sizeof(_Tp)>0

使用boost::scoped_ptr而不是std::unique_ptr时也会发生类似的错误。我是否正确理解了这一点?这意味着AImpl的前向声明是不够的


当添加构造函数和析构函数时,一切正常。原因是什么?是因为默认值是内联的,因此看不到AImpl的大小吗?当添加构造函数和析构函数时,编译器假设这些定义知道AImpl的大小。

解构函数需要知道完整的定义
AImpl
,因为它删除了它。所以问题是,
unique\u ptr
析构函数位于哪里?它是一个模板,所以问题是关于实例化点

析构函数在第一次使用时被实例化。构造函数和包含类的析构函数都使用它(如果构造函数的主体抛出异常,则构造函数需要它)。因此,
unique_ptr
析构函数在
A
的构造函数或析构函数所在的位置被实例化,以先到者为准

如果默认为这些特殊成员,则它们将在类主体之后立即生成,即在标题中,其中
AImpl
的大小未知


如果您改为在类中声明它们,然后放入定义(您可以
=default
这些定义)在
.cpp
中,在对
AImpl
进行完整定义之后,
unique_ptr
析构函数在那里被实例化。

中对这个问题进行了很好的讨论。析构函数不需要知道大小;内存管理会处理这个问题。但是,它需要知道如何析构函数对象,并且假定一个完整的类(以知道是否存在一个非平凡的析构函数)。@JamesKanze很好的观点,修正了它。
#include "A.hpp"

int main()
{
    A a;
}