删除完整的类类型会导致未定义的行为吗?
Could deleting complete class type result in undefined behavior?
我发现自己在理解以下引用自c++标准5.3.5$5的句子方面有困难:(强调是我的)
如果被删除的对象在删除时具有不完整类类型,并且完整类具有重要析构函数或释放函数,则该行为未定义。
我知道这个删除不完整类型的问题已经在SO中讨论了几次,我可以理解为什么删除不完整类类型是未定义的行为。这个问题解释得很好。
我不明白的是关于完整类类型的部分。这是否意味着删除完整类的对象具有非平凡析构函数或释放函数是未定义的行为?如果是,请给出一些代码来说明它可能导致的未定义行为
在相关情况下,未定义行为有两个先决条件:
- 对象通过指向不完整类型的指针被删除;
- 被删除对象的完整类具有重要的析构函数或(用户定义的)释放函数。
如果这两个条件中的任何一个为假,则没有未定义的行为(至少由于正在讨论的关注点)。
这特别意味着
-
删除complete类型的对象是安全的(因为将执行正确的析构函数和/或释放函数)。
-
通过指向不完整类型的指针删除带有普通析构函数且没有用户定义的释放函数的对象是安全的(因为在没有完整类型信息的情况下,编译器不会调用析构函数,而是使用默认的释放函数,这完全符合通过指向完整类型的指针执行删除的情况)。
让我试着用下面的代码来解释我所理解的:
struct Foo;
struct Bar;
Foo* newFoo();
Bar* newBar();
int main()
{
// Get a pointer to Foo, somehow
Foo* fp = newFoo();
// Get a pointer to Bar, somehow
Bar* bp = newBar();
// Foo is an incomplete class at this point.
// This is OK since Foo has a trivial destructor.
delete fp;
// Bar is an incomplete class at this point.
// Not OK since Bar has a non-trivial destructor.
// This is cause for undefined behavior.
delete bp;
}
struct Foo {};
struct Bar {
Bar() { data = new int[10]; }
~Bar(){ delete [] data; }
int* data;
};
Foo* newFoo()
{
return new Foo;
}
Bar* newBar()
{
return new Bar;
}
这是否意味着删除一个完整类的对象有一个非平凡的析构函数或一个释放函数是未定义的行为?
不,因为那意味着
class Foo {
public:
~Foo() { /*do something*/ };
};
是未定义的行为,而不是这样。
您似乎已经知道,删除具有不完整类类型的对象是未定义行为。问题是,只有当类具有非平凡的析构函数/解分配时,它才是未定义行为。
在这种情况下不是未定义行为:
//Foo is forward declared somewhere and destructed
//This is the class definition not available at the point that it is destructed
class Foo {
public:
//~Foo() = default;
};
只有在这种情况下才未定义
class Foo {
public:
~Foo() { /*do something*/ };
};
请注意,即使Foo
具有平凡的析构函数/释放,如果Foo
继承自另一个具有非平凡的析构函数/释放的类,它仍然是未定义的行为。
相关文章:
- 在UE4中使用未定义类型'UTextBlock'
- 删除[]具有不同类型的未定义行为?
- 在硬件SIMD矢量指针和相应类型之间进行"interpret_cast"是一种未定义的行为吗
- 错误:未定义对"静脉类型信息::电池访问"的引用
- 在头文件中使用opencv类型来实现未定义的标识符
- 为什么这种类型的双关语不是未定义的行为?
- 在C++中,转换为simd类型是否有未定义的行为
- 是std::memcpy在不同的可复制类型之间的未定义行为
- 交换未定义数据类型中的字节顺序
- 具有未声明/未定义类型的 typedef 结构
- 对静态常量积分类型的未定义引用
- 为什么 std::memcpy(作为类型双关语的替代方案)不会导致未定义的行为?
- 为什么内置类型的对象上的溢出会导致异常/未定义的行为?
- static_cast实际上不是对象类型的类型是未定义的行为吗?
- 共享库中非模板基的模板子类导致未定义的符号类型信息'class'链接错误
- icu::SimpleDate格式使用未定义类型的编译器错误
- 将不相关类型的对象reinterpret_cast空类是未定义的行为吗?
- 类型特征检查 CRTP 派生,在基类中,问题是未定义的类型
- C++ 使用未定义类型
- 未定义类型的重载