我有c-Structure,我想嵌入一个cpp类而不会中毒我的全局命名空间,所以我不想包含c-header。
这就是为什么我要使用具有前向声明结构名称的智能范围指针(QScopedPointer
或boost::scoped_ptr
)。
我不明白的是在编译时失败的两个提到的作用域指针的实现:
升压:
错误C2027:使用未定义的类型' xxx'
template<class T> inline void checked_delete(T * x)
{
// intentionally complex - simplification causes regressions
typedef char type_must_be_complete[ sizeof(T)? 1: -1 ]; // < here
(void) sizeof(type_must_be_complete);
delete x;
}
和Qt中的相同:
错误C2027:使用未定义的类型&#39; xxx&#39;
template <typename T>
struct QScopedPointerDeleter
{
static inline void cleanup(T *pointer)
{
// Enforce a complete type.
// If you get a compile error here, read the section on forward declared
// classes in the QScopedPointer documentation.
typedef char IsIncompleteType[ sizeof(T) ? 1 : -1 ]; // < here
(void) sizeof(IsIncompleteType);
delete pointer;
}
};
引用的文档对我没有帮助。它表示前向声明的类的析构函数不必是内联的,并且必须在每个可能的范围内清除指定指针时都可用。但我的c结构没有析构函数。
所以我有两个问题:
答案 0 :(得分:9)
答案 1 :(得分:6)
我的c-Structure没有析构函数。
首先,否。你的struct实际上有一个析构函数 - implicitly-declared destructor 。
无论如何,让我们继续吧。
delete pointer;
编译此代码时,我们应该调用*pointer
的析构函数。但是,如果*pointer
是不完整类型,我们就无法知道要调用的析构函数。在这种情况下,标准[expr.delete]表示它会导致未定义的行为。
如果被删除的对象在删除时具有不完整的类类型,并且完整的类具有非平凡的析构函数或释放函数,则行为是未定义的。
正如您所看到的,如果您的结构没有非平凡的析构函数或释放函数(特定于类operator delete
),那么它不是UB。但是,您可能可以在结构中添加析构函数 - 将执行。如果你没有解决这一点,它就变成了错误的bug。 (编译器不必报告它;它只是UB,而不是非法代码。)所以不被认为是一种好习惯。
因此,删除不完整的类型确实是我们应该避免的。为了避免这种情况,我们使用了这个技巧。
typedef char type_must_be_complete[ sizeof(T)? 1: -1 ]; // < here
(void) sizeof(type_must_be_complete);
如果sizeof(T)
是不完整类型,T
是非法代码,因此在程序因UB而疯狂之前,它可以减少编译时错误。
我强烈建议你尽管加快速度,但要包括它;虽然你的结构很简单,并且没有operator delete
,但是可以在不修复的情况下添加它们,这会导致UB。
答案 2 :(得分:0)
也许此链接将帮助您找出答案: http://www.bnikolic.co.uk/blog/cpp-checked-delete.html
由于“ boost / checked_delete.hpp” 标头,scoped_ptr 需要使用完全定义的类型作为其模板参数。
就这些事情而言,我个人更喜欢 std :: unique_ptr (例如,当 Init()方法用于一些构造是私有的),但boost没有唯一的指针。
有时,如果方便的话,您可以使用 boost :: shared_ptr ,因为它不表示这些错误。