2012-07-09 38 views
3

可能重複調用構造:
Can placement new for arrays be used in a portable way?爲()使用malloc分配的對象陣列

我想分配物T的陣列,並使用對象的構造初始化對象。這是很容易用C++ new

T * pointerT = new T [arraySize]; 

它會叫牛逼構造所有arraySize對象。 但是,由於某種原因,我必須使用C memalign而不是新的。在這種情況下,我最終使用以下代碼

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

new (pointerT) T()只調用一次T構造函數。但是,我需要爲所有對象調用T構造函數,而不僅僅是第一個。

我很感激您的幫助。

回答

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; 

,享受一個異常安全,移動意識到,迭代意識到,範圍爲基礎,爲意識到,等等,矢量與對齊的存儲。

+0

+1對齊分配器暗示 – 2012-07-09 19:46:32

+0

感謝Alex,這很有幫助 – ARH 2012-07-09 20:16:14

3

如果T是可複製,是這樣的:

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

應該做的伎倆。它甚至可以處理破壞的對象,如果異常拋出一部分的話,那些對象會被構建。