如何使用 placement new 确定对象是否已放置

How to determine if object has been placed using placement new

使用 placement new 语法,我应该可以做这样的事情:

char *buffer  = new char[sizeof(MyClass)]; //pre-allocated buffer
MyClass *my_class = new (buffer) MyClass; //put da class there 

现在假设我只做第一行,而不做第二行。有没有一种方法可以在代码中确定是否已正确分配缓冲区,但那里尚未实例化 MyClass 类型的对象?

该语言没有提供任何内置机制来提供该信息,至少 none 据我所知是这样。您必须添加自己的簿记代码来跟踪此类信息。

您可以维护一个 static table 的 this 指针值,您可以在构造函数和析构函数中将其变异为 MyClass。然后在需要时根据 buffer 的特定值检查它。

不要忘记考虑移动语义的影响。做对会很棘手。

出于调试目的,您可以将特殊成员 signature 添加到 MyClass 并将其值设置为常量

class MyClass {
   public:
      MyClass() : signature(762347562374) {}
      bool isValidSignature() const { return signature==762347562374; }
   private:
      unsigned long long signature;
      <other members>
};

然后,检查如下:

char *buffer  = new char[sizeof(MyClass)]; //pre-allocated buffer
MyClass *my_class = new (buffer) MyClass; //put da class there 
if (my_class->isValidSignature())
   <this means that the object has been allocated correctly, with a high probability>
}

您可以将与签名相关的所有内容放在适当的 #ifdef 中,这样它只会在调试模式下运行。

不是没有自己跟踪它。

一个解决方案是围绕 std::allocator 创建一个包装器。

template<class T>
class MyAllocator
{
public:
    T* allocate(std::size_t count = 1) 
    { 
        return allocator_.allocate(count);
    }

    template<class... Args>
    void construct(T* ptr, Args&&... args)
    {
        allocator_.construct(ptr, std::forward<Args>(args)...);
        allocated_ = true;
    }

    bool IsAllocated() const
    {
        return allocated_;
    }

private:
    std::allocator<T> allocator_;
    bool allocated_;

};

原代码:

char *buffer  = new char[sizeof(MyClass)]; //pre-allocated buffer
MyClass *my_class = new (buffer) MyClass; //put da class there 

要动态地确定 放置new 是否已执行,有关它的信息必须存储在某处。该语言不提供该服务。所以你必须自己做,主要有两种可能的方式之一:

  • 正在缓冲区中存储信息。
    对于这种情况,缓冲区必须在分配时初始化。例如。只需在 new 表达式的末尾添加 () 即可。否则无法保证缓冲区内容看起来不像一个对象。两个子案例:
    1. 通过在缓冲区中为标志添加空间。
    2. 通过将标志作为对象的成员。
      在多态 class 的情况下,实际上会有一个非零 vtable 指针,可以用作标志。
  • 在外部存储信息。
    对于这种情况,缓冲区不需要在分配时初始化。有无数种可能性,包括
    1. 一个简单的 bool 变量。
    2. 指向所有此类对象的指针集合。
    3. 向黑猩猩发出的声音信号,稍后会对其进行查询。