【问题标题】:How to determine if object has been placed using placement new如何使用placement new确定是否已放置对象
【发布时间】:2016-02-10 16:21:18
【问题描述】:

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

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

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

【问题讨论】:

  • 为什么需要这个?好像不对。
  • @ZDF 事实证明,当我更仔细地研究这个问题时,我可能不会。所以你的问题的答案似乎很清楚 - 缺乏经验...... :)

标签: c++ placement-new


【解决方案1】:

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

【讨论】:

    【解决方案2】:

    出于调试目的,您可以将特殊成员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 中,以便仅在调试模式下运行。

    【讨论】:

    • 当标志产生有保证的行为时,为什么要使用统计方法?
    • @Cheersandhth.-Alf 您所说的问题似乎有一些简单的解决方案。我不明白;也许您应该添加一个答案来解释“标志”的含义。
    • 我讨厌在调试版本中具有不同(更大)大小的类
    【解决方案3】:

    原码:

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

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

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

    【讨论】:

      【解决方案4】:

      您可以维护一个包含this 指针值的static 表,您可以在构造函数和析构函数中将其更改为MyClass。然后在需要时对照特定值 buffer 进行检查。

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

      【讨论】:

        【解决方案5】:

        不是没有自己跟踪。

        一种解决方案是围绕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_;
        
        };
        

        【讨论】:

        • 这与直接使用bool 变量相比如何?
        • 只是觉得这是一个很好的总结方式。
        猜你喜欢
        • 2018-02-20
        • 1970-01-01
        • 2020-02-24
        • 1970-01-01
        • 2013-03-25
        • 2017-07-15
        • 1970-01-01
        • 2023-03-22
        • 2014-06-15
        相关资源
        最近更新 更多