可能重复:
Can placement new for arrays be used in a portable way?
我想分配对象T的数组并使用对象构造函数初始化对象。使用c ++ new
:
T * pointerT = new T [arraySize];
它将为所有arraySize
个对象调用T构造函数。
但是,出于某种原因,我必须使用C memalign
而不是新的。在这种情况下,我最终使用以下代码
T * pointerT = (T*) memalign(64,arraySize * sizeof(T));
new (pointerT) T();
new (pointerT) T()
只调用一次T构造函数。但是,我需要为所有对象调用T构造函数,而不仅仅是第一个。
感谢您的帮助。
答案 0 :(得分:8)
循环中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<T, aligned_allocator<T, 64>> 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 :(得分:3)
如果T
是可复制的,请执行以下操作:
std::uninitialized_fill_n( pointerT, arraySize, T()); // #include <memory>
应该做的伎俩。如果异常被抛出,它甚至会处理为你构造的破坏对象。