C++ 在(虚拟)父类中放置新对象

C++ 在(虚拟)父类中放置新对象,c++,crtp,C++,Crtp,我有这个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类型,因此没有奇特的构造函数和析构函数 我用g

我有这个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与派生类的this相同,所以您没有覆盖任何超出分配的内存。

要在内存中的正确位置重新创建子类型,您必须强制转换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与派生类的this相同,您没有覆盖任何超出分配的内存。

除了静态\u cast之外,我还建议首先调用对象上的dtor

template <class T>
struct S {
    void clear() {
        auto this_ptr = static_cast<T*>(this)
        this_ptr->~T();
        new (this_ptr) T();
    }
};
除此之外,我还建议首先对对象调用dtor

template <class T>
struct S {
    void clear() {
        auto this_ptr = static_cast<T*>(this)
        this_ptr->~T();
        new (this_ptr) T();
    }
};

很好,谢谢。静态演员阵容有什么意义?它能改变这个的实际值吗?@user2717954是的。this指针可以指向基指针或派生指针,因为它们在内存中的偏移量可能不同,具体取决于它们的内容,或者是否使用了多重继承。std::is_minally_destructible要求T的析构函数不是虚的。如果S是虚拟的,或者即使SS继承S的类是虚拟的,而S本身不是虚拟的,是否有一些解决方法t@user2717954是的,它不能是虚拟的。如果您想要一个非平凡的或虚拟的析构函数,您必须在创建新的objectNice之前使用static_castthis->~T调用它,谢谢。静态演员阵容有什么意义?它能改变这个的实际值吗?@user2717954是的。this指针可以指向基指针或派生指针,因为它们在内存中的偏移量可能不同,具体取决于它们的内容,或者是否使用了多重继承。std::is_minally_destructible要求T的析构函数不是虚的。如果S是虚拟的,或者即使SS继承S的类是虚拟的,而S本身不是虚拟的,是否有一些解决方法t@user2717954是的,它不能是虚拟的。如果您想要一个非平凡或虚拟析构函数,则必须在创建新对象之前使用static\u casthis->~T调用它