3

重複の可能性:
配列の新しい配置を移植可能な方法で使用できますか?

オブジェクト T の配列を割り当て、オブジェクト コンストラクターを使用してオブジェクトを初期化したい。これは c++ を使用すると簡単ですnew:

T * pointerT = new T [arraySize];

arraySizeすべてのオブジェクトに対して T コンストラクターを呼び出します。ただし、何らかの理由memalignで new の代わりに C を使用する必要があります。この場合、次のコードを使用することになります

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

new (pointerT) T()T コンストラクターを 1 回だけ呼び出します。ただし、最初のオブジェクトだけでなく、すべてのオブジェクトに対して T コンストラクターを呼び出す必要があります。

私はあなたの助けに感謝します.

4

2 に答える 2

8

new (pointerT) T()ループで行います。デストラクタがオブジェクトと呼び出しを破棄するオブジェクトの内部に保持してください(たとえば、それを呼び出します)。コンストラクタでは、次のようにします。pointerTfreealigned_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;

例外安全、移動認識、イテレータ認識、範囲ベースのforループ認識など、整列されたストレージを備えたベクトルをお楽しみください。

于 2012-07-09T19:21:28.480 に答える
3

がコピー可能である場合T、次のようになります。

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

トリックを行う必要があります。途中で例外がスローされた場合に構築されたオブジェクトの破棄も処理します。

于 2012-07-09T21:50:35.603 に答える