当它是 noop 时是否需要调用一个非平凡的析构函数?
is it required to call a non-trivial destructor when it is a noop?
当您知道在这种特定情况下析构函数是 noop 时,标准是否要求调用非平凡的析构函数?
如果不调用析构函数,代码是否可能被编译器破坏?
用例是一个包含动态分配指针的 class。默认情况下,此指针由构造函数中的 new
获取。 this class 也可以从分配器中获取其动态分配的指针。 class 跟踪它是如何获得它的指针并在析构函数中调用 delete
如果指针是由 new
获得的,如果它是由分配器获得的则什么都不调用,因为分配器将释放记忆。存储在动态内存中的数据只是普通类型,因此不需要调用它们的析构函数。
所以问题是,如果我知道 class 是通过分配器获得其指针的,那么我还需要调用析构函数吗?
这是一个最小的简化示例,所有与问题不直接相关的内容都已删除。
struct Allocator {
void* ptr = nullptr;
void* Allocate(size_t size) {
ptr = malloc(size);
return ptr;
}
~Allocator() { // allocator will cleanup
if (ptr)
free(ptr);
}
};
struct C {
int* ptr;
bool need_cleanup;
C() {
ptr = new int[10];
need_cleanup = true;
}
C(Allocator& A) {
ptr = (int*)A.Allocate(10 * sizeof(int));
need_cleanup = false;
}
~C() { // non-triviall because user-defined.
if (need_cleanup)
delete[] ptr;
// noop if need_cleanup is false.
}
};
int main()
{
Allocator A;
alignas(C) char buffer[sizeof(C)];
C* c = new(buffer) C(A);
/// is it required to call c->~C();
}
没有
For an object of a class type with a non-trivial destructor, the program is not required to call the destructor explicitly before the storage which the object occupies is reused or released; however, if there is no explicit call to the destructor or if a delete-expression ([expr.delete]
) is not used to release the storage, the destructor shall not be implicitly called and any program that depends on the side effects produced by the destructor has undefined behavior.
您不依赖于 ~C
的任何 side-effects,因此您没有未定义的行为。
N.B。你可能应该放置 new[]
你的 A.Allocate
'd int[10]
C(Allocator& A) {
ptr = new (A.Allocate(10 * sizeof(int))) int[10];
need_cleanup = false;
}
当您知道在这种特定情况下析构函数是 noop 时,标准是否要求调用非平凡的析构函数?
如果不调用析构函数,代码是否可能被编译器破坏?
用例是一个包含动态分配指针的 class。默认情况下,此指针由构造函数中的 new
获取。 this class 也可以从分配器中获取其动态分配的指针。 class 跟踪它是如何获得它的指针并在析构函数中调用 delete
如果指针是由 new
获得的,如果它是由分配器获得的则什么都不调用,因为分配器将释放记忆。存储在动态内存中的数据只是普通类型,因此不需要调用它们的析构函数。
所以问题是,如果我知道 class 是通过分配器获得其指针的,那么我还需要调用析构函数吗?
这是一个最小的简化示例,所有与问题不直接相关的内容都已删除。
struct Allocator {
void* ptr = nullptr;
void* Allocate(size_t size) {
ptr = malloc(size);
return ptr;
}
~Allocator() { // allocator will cleanup
if (ptr)
free(ptr);
}
};
struct C {
int* ptr;
bool need_cleanup;
C() {
ptr = new int[10];
need_cleanup = true;
}
C(Allocator& A) {
ptr = (int*)A.Allocate(10 * sizeof(int));
need_cleanup = false;
}
~C() { // non-triviall because user-defined.
if (need_cleanup)
delete[] ptr;
// noop if need_cleanup is false.
}
};
int main()
{
Allocator A;
alignas(C) char buffer[sizeof(C)];
C* c = new(buffer) C(A);
/// is it required to call c->~C();
}
没有
For an object of a class type with a non-trivial destructor, the program is not required to call the destructor explicitly before the storage which the object occupies is reused or released; however, if there is no explicit call to the destructor or if a delete-expression (
[expr.delete]
) is not used to release the storage, the destructor shall not be implicitly called and any program that depends on the side effects produced by the destructor has undefined behavior.
您不依赖于 ~C
的任何 side-effects,因此您没有未定义的行为。
N.B。你可能应该放置 new[]
你的 A.Allocate
'd int[10]
C(Allocator& A) {
ptr = new (A.Allocate(10 * sizeof(int))) int[10];
need_cleanup = false;
}