我如何使用unique_ptr pimpl?

这里是我尝试使用unique_ptr for pimpl时看到的简化。 我select了unique_ptr,因为我真的希望类拥有指针 – 我希望pimpl指针和类的生命期是相同的。

无论如何,这是标题:

#ifndef HELP #define HELP 1 #include <memory> class Help { public: Help(int ii); ~Help() = default; private: class Impl; std::unique_ptr<Impl> _M_impl; }; #endif // HELP 

这里是来源:

 #include "Help.h" class Help::Impl { public: Impl(int ii) : _M_i{ii} { } private: int _M_i; }; Help::Help(int ii) : _M_impl{new Help::Impl{ii}} { } 

我可以将它们编译成一个库。 但是当我尝试在testing程序中使用它时,

 ed@bad-horse:~/ext_distribution$ ../bin/bin/g++ -std=c++0x -o test_help test_help.cpp Help.cpp In file included from /home/ed/bin/lib/gcc/x86_64-unknown-linux-gnu/4.7.0/../../../../include/c++/4.7.0/memory:86:0, from Help.h:4, from test_help.cpp:3: /home/ed/bin/lib/gcc/x86_64-unknown-linux-gnu/4.7.0/../../../../include/c++/4.7.0/bits/unique_ptr.h: In instantiation of 'void std::default_delete<_Tp>::operator()(_Tp*) const [with _Tp = Help::Impl]': /home/ed/bin/lib/gcc/x86_64-unknown-linux-gnu/4.7.0/../../../../include/c++/4.7.0/bits/unique_ptr.h:245:4: required from 'void std::unique_ptr<_Tp, _Dp>::reset(std::unique_ptr<_Tp, _Dp>::pointer) [with _Tp = Help::Impl; _Dp = std::default_delete<Help::Impl>; std::unique_ptr<_Tp, _Dp>::pointer = Help::Impl*]' /home/ed/bin/lib/gcc/x86_64-unknown-linux-gnu/4.7.0/../../../../include/c++/4.7.0/bits/unique_ptr.h:169:32: required from 'std::unique_ptr<_Tp, _Dp>::~unique_ptr() [with _Tp = Help::Impl; _Dp = std::default_delete<Help::Impl>]' Help.h:6:7: required from here /home/ed/bin/lib/gcc/x86_64-unknown-linux-gnu/4.7.0/../../../../include/c++/4.7.0/bits/unique_ptr.h:63:14: error: invalid application of 'sizeof' to incomplete type 'Help::Impl' 

这是一个众所周知的安全function 。 我试图跟随。

我的问题是,如果我把一个头文件中的Help :: Impl声明,它似乎会消除pimpl的任何优势。 类布局对用户是可见的。 定义是隐藏的,但我可以用帮助类和私人成员做到这一点。 此外,包括Impl的声明带来了新的标题,我希望保持分开。

我错过了什么? 人们在Impl宣言中放什么? 我在做帮助吗? 哎呀!

我相信你的test_help.cpp实际上可以看到你宣称默认的~Help()析构函数。 在这个析构函数中,编译器也试图生成unique_ptr析构函数,但是它需要Impl声明。

所以,如果将析构函数定义移动到Help.cpp,则该问题应该消失。

– 编辑 – 你也可以在cpp文件中定义析构函数为默认值:

 Help::~Help() = default;