2016-10-20 3 views
0

私は、多くの場合、多次元配列を扱う、そして基になるデータをコピーせずstd::vectorまたはstd::vectorさんのstd::vectorが、基準を使用してインスタンス化することはできませんので、私は、std::vectorの大ファンではありません。unique_ptrをするのは

一次元アレイの場合、私は

template<typename T> 
using deleted_aligned_array = std::unique_ptr<T[], std::function<void(T*)> >; 

template<typename T> 
deleted_aligned_array<T> deleted_aligned_array_create(size_t n) { 
    return deleted_aligned_array<T>((T*)_mm_malloc(n*sizeof(T),16), [](T* f)->void { _mm_free(f);}); 
} 

これは非常に便利であり、私はまた、ゼロの大きさのために働く動的サイズの配列をインスタンス化することができ、次の使用します。さらに、std::forwardを使用して、コピーせずにデータを渡すことができます。 2次元配列の場合

、私は

template<typename T> 
using deleted_aligned_array2 = std::unique_ptr<T*,std::function<void(T**)>>; 

template<typename T> 
deleted_aligned_array2<T> deleted_aligned_array_create(size_t m, size_t n) { 
    auto arr = deleted_aligned_array2(new T*[m](), [&](T** x) { 
               if (malloc_usable_size(x) > 0) { 
               _mm_free(&(x[0][0])); 
               } 
               delete[] x;}); 
    if (m*n > 0) { 
    arr.get()[0] = (T*) _mm_malloc(m*n*sizeof(T),16); 

    // Row pointers 
    for (size_t iRow = 1; iRow < m; iRow++) { 
     (m_data.get())[iRow] = &(m_data.get()[0][iRow*n]); 
    } 
    } 
    return arr; 
} 

それはゼロサイズの配列のために働くような何かをしたいと思いますが、私は、明白な理由のためにvalgrindからinvalid read of size 8をエラーが発生します。

std::unique_ptrメンバを保持してクラス全体を作成せずに、これを優雅な方法で解決することは可能ですか?私はmove-constructor、move-assignmentなどを実装します。最終的に、これを一般化して寸法

template<typename T, size_t Dim> 
deleted_aligned_array<T,D> deleted_aligned_array_create(...); 

返される配列を再帰的に初期化行ポインタユニークなポインタであるべきであり、それは、例えばゼロサイズの配列をサポートしなければなりません

auto arr = deleted_aligned_array_create<float,3>(4,5,10); 

は、行と列のポインタを持つ3次元配列を返します。

問題: 1)簡単な方法で無効なデータを読み込まないようにしてください。 2)テンプレートのパラメータDを使用して、T*,T**の型を生成し、単純にDを渡して、再帰的に行ポインタを生成するコードに渡します(既にこれがあります)。 3)ポータブルな方法で行うのが好ましい。サイズは、私は一種の解決策を見つけたが、それは非常にエレガントではありません事前

+0

STDの* "STD ::ベクターまたはスタンダード::ベクトルとすることができる::コピーせずに参照を使用して、ベクトルの基礎となるデータ "*あなたはどういう意味ですか? – Jarod42

+1

多次元配列を実装する良い方法は、配列を平坦化し、インデックスを "手動で"計算することです。 – Jarod42

+0

インスタンスを作成する必要がある関数の引数型としてstd :: vectorを使用したい場合は、これがコピーを発行します。私はしばしば多次元配列のサブアレイを使い、コピーを避けたい。 –

答えて

0

で0

おかげであるときmalloc_usable_sizeは、GNUの拡張や無効読み込み中x結果でそれを呼び出すことです。より洗練されたソリューションをお持ちの場合は、回答を投稿してください。ここでの解決策は、一度高次元になるとかなり醜いです。

template <class T, size_t D> 
class deleted_aligned_multi_array { 
}; 

template <class T> 
class deleted_aligned_multi_array<T,1> : public std::unique_ptr<T[], std::function<void(T*)> > { 
    deleted_aligned_multi_array(size_t n) : 
    std::unique_ptr<T[], std::function<void(T*)> >((T*)_mm_malloc(n*sizeof(T),16), 
                [](T* f)->void { _mm_free(f);}) {} 
}; 

template <class T> 
class deleted_aligned_multi_array<T,2> { 
public: 
    typedef T** pointer; 
    typedef std::unique_ptr<T*, std::function<void(T**)>> deleted_unique_array; 

    deleted_aligned_multi_array() : m(0), n(0), data() {} 

    deleted_aligned_multi_array(size_t m, size_t n) : m(m), n(n) { 
    if (m*n > 0) { 
     data = deleted_unique_array(new T*[m](), 
            [&](T** x) { 
             if (sps::msize(x) > 0) { 
             _mm_free(&(x[0][0])); 
             } 
             delete[] x;}); 

     data.get()[0] = (T*) _mm_malloc(m*n*sizeof(T),16); 

     for (size_t iRow = 1; iRow < m; iRow++) { 
     (data.get())[iRow] = &(data.get()[0][iRow*n]); 
     } 
    } 
    else { 
     data.reset(); 
    } 
    } 

    deleted_aligned_multi_array(deleted_aligned_multi_array&& other) : m(other.m), n(other.n), 
           data(std::move(other.data)) {} 

    deleted_aligned_multi_array& operator=(deleted_aligned_multi_array&& other) { 
    if (this != &other) { 
     data = std::move(other.data); 
     m = other.m; 
     m = other.n; 
    } 
    return *this; 
    } 

    T& operator()(size_t i, size_t j) { 
    return this->data.get()[0][i*n + j]; 
    } 

    T* operator[](size_t m) { 
    return &(data.get()[m][0]); 
    } 

    const T* operator[](size_t m) const { 
    return data.get()[m]; 
    } 

    pointer get() const { 
    return data.get(); 
    } 

    void reset(pointer __p = pointer()) { 
    data.reset(__p); 
    } 

    template<typename _Up> 
    void reset(_Up) = delete; 

private: 
    deleted_aligned_multi_array(const deleted_aligned_multi_array& other) = delete; 
    deleted_aligned_multi_array& operator=(const deleted_aligned_multi_array& a) = delete; 

public: 
    size_t m;     ///<Number of rows 
    size_t n;     ///<Number of columns 
    deleted_unique_array data; ///<Data 
}; 

サブアレイにアクセスするためのユーティリティ関数、簡単

template <class T> 
std::unique_ptr<T*, std::function<void(T*)> sub_array(size_t m, size_t n, size_t i, size_t j) { 
    // Establish row pointers with reference i and j and dimension mxn. 
}