我试图将boost::scoped_ptr
与我的实现类一起使用,该实现类仅在包含类的cpp文件中可见。包含类有一个显式定义的析构函数(不是内联的),但我的编译器(Borland C ++ 5.6.4)无法编译。
如果我改为使用boost::shared_ptr
,则相同的示例将按预期编译并运行。
我做错了什么?
编辑:很遗憾忘记在这里显示源代码,编译器错误和(预期)输出:
档案check_shared.cpp
:
// shortened.
#include "SmartPtrTest.h"
void check_shared()
{
Containing t;
}
档案SmartPtrTest.h
:
#include <boost/noncopyable.hpp>
#include <boost/smart_ptr.hpp>
class Impl;
#define smart_ptr boost::scoped_ptr
class Containing: private boost::noncopyable
{
public:
Containing();
~Containing();
private:
smart_ptr<Impl> impl;
};
档案SmartPtrTest.cpp
:
#include "SmartPtrTest.h"
#include <iostream>
using namespace std;
class Impl {
public:
Impl() {
cout << "ctr Impl" << endl;
}
~Impl() {
cout << "dtr Impl" << endl;
}
};
Containing::Containing(): impl(new Impl)
{
cout << "ctr Containing" << endl;
}
Containing::~Containing()
{
cout << "dtr Containing" << endl;
}
...类似于undefined structure 'Impl'
(它的德语: Undefinierte Struktur&#39; Impl&#39; )。编译文件check_shared.cpp
时,编译器在此函数的boost/checked_delete.hpp
中的文件typedef
中停止:
template<class T> inline void checked_delete(T * x)
{
// intentionally complex - simplification causes regressions
typedef char type_must_be_complete[ sizeof(T)? 1: -1 ];
(void) sizeof(type_must_be_complete);
delete x;
}
我在使用boost::share_ptr
时得到的输出结果显示ctr和dtr按预期调用。
ctr Impl
ctr Containing
dtr Containing
dtr Impl
答案 0 :(得分:1)
只要“实现”类在智能指针可能被销毁的任何时刻完成,它就应该工作。这不仅发生在析构函数中,而且发生在构造函数中 - 如果它们因异常而退出,则必须销毁指针成员。
因此,请确保在实现类的定义之后,在源文件中定义了构造函数和析构函数。
(这是基于猜测你因为尝试销毁一个不完整的类型而得到编译错误。如果你得到不同的错误,或者意外的运行时行为,或者更改没有修复它,那么请更新问题以证明实际问题。)
答案 1 :(得分:1)
这绝对是由于编译器错误造成的。不幸的是它仍然存在于C ++ Builder XE8中。请在此处查看此相关问题,以及Andy Prowl的答案:Is it valid for a C++ compiler to implicitly instantiate ALL member functions of a template class?
问题报告给Embarcadero:bcc32 compiler causes undefined behavior when using std::auto_ptr with PIMPL idiom because template instantiation rules do not follow C++ spec
如果你可以使用Embarcadero的一个较新的基于clang的编译器,你应该没问题。我的测试用例传入了64位的clang编译器。
更新:我们通过编写与unique_ptr
类似的智能指针类解决了这个问题,因为它包含一个未在线实现的checked_delete
函数在课堂上。相反,您必须在一个包含私有类实现的一个翻译单元中显式实例化checked_delete
函数。宏用于帮助解决这个问题。那就是:
template<class X> class unique_ptr_bcc32 {
// Deletes the object using operator delete:
private: static void checked_delete(X* p);
// <snip>
}
稍后,在CPP文件中:
class PIMPL { /* snip implementation */ };
// You can simplify this by way of a macro:
template <> void unique_ptr_bcc32<PIMPL>::checked_delete(PIMPL* p) {
typedef char type_must_be_complete[sizeof(PIMPL) ? 1 : -1];
static_cast<void>(sizeof(type_must_be_complete));
delete p;
}
当涉及模板实例化和删除时,编译器没有留下有趣的业务空间。