在(虚拟)parent class 中的新位置
placement new in a (virtual) parent class
我有这个 CRTP:
template <class T>
struct S {
void clear() { new (this) T; }
};
class SS : public S<SS> {
int i = 5;
};
int main() {
SS s;
s.clear();
}
clear()
是否保证按预期工作? S
是否为虚拟是否重要?
就此而言,我们可以假设所有继承 S
的 类 除了基本类型或 POD 类型之外没有任何其他类型,因此没有花哨的构造函数和析构函数。
我用 gcc 编译,valgrind 似乎没有抱怨,但感觉很奇怪。
要在内存中的正确位置重新创建子类型,您必须转换 this
指针。
此外,如果您不调用析构函数,则必须断言该类型是可平凡破坏的:
template <class T>
struct S {
void clear() {
static_assert(std::is_base_of_v<S, T>);
static_assert(std::is_trivially_destructible_v<T>);
new (static_cast<T*>(this)) T;
}
};
Valgrind 没有发出任何警告,因为来自基础的 this
与派生的 class 相同,您没有覆盖分配的任何内存。
除了 static_cast<T*>(this)
,我还建议先在对象上调用 dtor。
template <class T>
struct S {
void clear() {
auto this_ptr = static_cast<T*>(this)
this_ptr->~T();
new (this_ptr) T();
}
};
我有这个 CRTP:
template <class T>
struct S {
void clear() { new (this) T; }
};
class SS : public S<SS> {
int i = 5;
};
int main() {
SS s;
s.clear();
}
clear()
是否保证按预期工作? S
是否为虚拟是否重要?
就此而言,我们可以假设所有继承 S
的 类 除了基本类型或 POD 类型之外没有任何其他类型,因此没有花哨的构造函数和析构函数。
我用 gcc 编译,valgrind 似乎没有抱怨,但感觉很奇怪。
要在内存中的正确位置重新创建子类型,您必须转换 this
指针。
此外,如果您不调用析构函数,则必须断言该类型是可平凡破坏的:
template <class T>
struct S {
void clear() {
static_assert(std::is_base_of_v<S, T>);
static_assert(std::is_trivially_destructible_v<T>);
new (static_cast<T*>(this)) T;
}
};
Valgrind 没有发出任何警告,因为来自基础的 this
与派生的 class 相同,您没有覆盖分配的任何内存。
除了 static_cast<T*>(this)
,我还建议先在对象上调用 dtor。
template <class T>
struct S {
void clear() {
auto this_ptr = static_cast<T*>(this)
this_ptr->~T();
new (this_ptr) T();
}
};