【问题标题】:Call constructor for object array allocated with malloc() [duplicate]为使用 malloc() 分配的对象数组调用构造函数 [重复]
【发布时间】:2012-07-09 05:45:36
【问题描述】:

可能重复:
Can placement new for arrays be used in a portable way?

我想分配对象 T 的数组并使用对象构造函数初始化对象。这很容易使用 c++ new

T * pointerT = new T [arraySize];

它将为所有 arraySize 对象调用 T 构造函数。 但是,出于某种原因,我必须使用 C memalign 而不是 new。在这种情况下,我最终使用以下代码

T * pointerT = (T*) memalign(64,arraySize * sizeof(T)); 
new (pointerT) T(); 

new (pointerT) T() 只调用一次 T 构造函数。但是,我需要为所有对象调用 T 构造函数,而不仅仅是第一个对象。

非常感谢您的帮助。

【问题讨论】:

    标签: c++ c oop memory-management constructor


    【解决方案1】:

    如果T 是可复制的,则类似于:

    std::uninitialized_fill_n( pointerT, arraySize, T()); // #include <memory>
    

    应该可以解决问题。如果在中途抛出异常,它甚至会为您销毁已构建的对象。

    【讨论】:

      【解决方案2】:

      循环执行new (pointerT) T()pointerT保留在一个对象中,该对象的析构函数会破坏对象并调用free(例如称为aligned_vector),并在构造函数中执行以下操作:

      ptrdiff_t k = 0;
      
      try
      {
          for (; k < n; k++)
              new (pointerT + k) T();
      }
      
      catch (...)
      {
          for (; k > 0; k--) (pointerT + k)->~T();
          free(pointerT);
          throw;
      }
      

      这样,如果构造失败,您可以通过事务处理而不会泄漏内存或资源。

      为此,就可重用性而言,最简单的方法是实现您自己的对齐感知分配器并使用std::vector,它为您处理异常安全(和许多其他好处)。

      这是一个示例分配器,C++11,带有编译时对齐规范(请提出改进​​和更正建议):

      template <typename T, size_t align>
      struct aligned_allocator
      {
          typedef T value_type;
          typedef T* pointer;
          typedef const T* const_pointer;
          typedef T& reference;
          typedef const T& const_reference;
          typedef size_t size_type;
          typedef ptrdiff_t difference_type;
      
          template <typename U>
          struct rebind { typedef aligned_allocator<U, align> other; };
      
          T* address(T& t) { return &t; }
      
          T* allocate(size_t n, const T* = 0) 
          {
              if (T* ans = memalign(align, n * sizeof(T))) return ans;
              else throw std::bad_alloc();
          }
      
          T* deallocate(T* p, size_t) { free(p); }
      
          size_t max_size() const 
          {
              return size_t(-align) / sizeof(T); 
          }
      
          template <typename U, typename... Args>
          void construct(U* p, Args&&... args)
          {
              ::new((void *)p U(std::forward<Args>(args)...);
          }
      
          template <typename U>
          void destroy(U* p) { p->~U(); }
      };
      

      示例用法:std::vector&lt;T, aligned_allocator&lt;T, 64&gt;&gt; v(42); 构造一个具有对齐存储和 64 个元素的向量。

      在 C++11 中你也可以这样做

      template <typename T, size_t align>
      using aligned_vector = std::vector<T, aligned_allocator<T, align>>;
      

      你现在可以使用

      aligned_vector<MyType, 64> v;
      

      并享受异常安全、移动感知、迭代器感知、基于范围的循环感知等,对齐存储的向量。

      【讨论】:

      • +1 对齐分配器建议
      猜你喜欢
      • 1970-01-01
      • 2012-04-29
      • 2014-06-30
      • 1970-01-01
      • 2012-09-21
      • 2013-02-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多