保存对象的攻击函数并稍后称呼它是明确定义的行为

Is it well defined behaviour to save a destructor adress of an object and call it later?

本文关键字:定义 攻击 对象 函数 保存      更新时间:2023-10-16

我目前正在使用C 编写的堆栈分配器。可以通过模板方法从此堆栈分配器中获取对象。一旦调用了另一种交易方法,应破坏这些对象。当实验不同的方法以实现灾难的调用时,我偶然发现了以下内容:

auto destructor = someObject->~SomeClass;
destructor();

灾难似乎被称为震源,但是这对我来说有点奇怪。我有以下问题:

  1. 这种定义明确的行为?
  2. 驱动器的类型是什么(我可以用什么替换自动关键字(?
  3. 我可以保存列表中不同类型的几个对象的所有驱动器地址并以后调用吗?

正如评论注释,这是未定义的行为/编译器扩展。

不过可以做您想做的事:

template<typename T>
std::function<void(T*)> defer_dtor()
{
   return [](T* ptr) {ptr->~T();};
}

或直接(更像您的问题,但独特的lambda类型不能直接添加到列表中。(

auto destructor = [&]{someObject->~SomeClass();};
destructor();

注意:这遵循您的问题,并且不调用delete ptr。这是否适当取决于上下文,但大概是您要包装delete ptr,您只会使用std::shared_ptr

[编辑]我错过了您的问题:"保存列表中不同类型的几个对象的所有破坏性地址"。

这将是一个问题。确切地说,设计问题。这些类型如何相关?如果通过继承,您不需要驱动器列表,而需要virtual驱动器。如果类型不相关,您如何匹配对象和保存的损坏器?如果您确实有所有这些对象的类型,为什么不直接调用->~Type()

我可以保存不同的几个对象的所有驱动器地址 列表中的类型并以后调用?

是。请注意,我的解决方案还将破坏对象的指针保留,而不仅仅是破坏对象。您可以做一些lambda魔术来实现这一点 一些低级帮助:

class GenericDestructor {
private:    
    const void* object;
    void(*destructor)(const void*);
public:
    template<class T>
    GenericDestructor(const T& _object) noexcept :
        object(std::addressof(_object)){
        destructor = [](const void* _object) {
            auto original = static_cast<const T*>(_object);
            original->~T();
        };
    };
    void operator () () noexcept {
        destructor(object);
    }
};

存储:

std::vector<GenericDestructor> storedDestructors;
auto needsToBeDeleted = new std::string();
storedDestructors.emplace_back(*needsToBeDeleted);

破坏所有存储的对象:

for(auto& storedDestructor : storedDestructors) storedDestructor();