2016-08-18 3 views
1

せずに、配列のうちのベクトルを作る:大雑把に、私はすべての場所で、このAPIを持っ割り当てとメモリコピー

void func(const vector<int> &vint); 

ひどく、設計されていますが、私は割り当て\コピーせずにそれに私のint*を渡す必要がありますされていますボトルネックだと分かったからです。 (複数のスレッドで同時にmemcpyを実行すると速くコピーされません)

私はこのようなクラスを書くことを考えた:

template<typename T> 
struct fake_vector { 
    fake_vector(T *array, size_t array_length) { 
     internal_vector.set_begin(array); 
     internal_vector.set_end(array + array_length); 
    } 
    ~fake_vector() { // let's reset our internal vector so it won't try to deallocate our memory 
     internal_vector.set_begin(nullptr); 
     internal_vector.set_end(nullptr); 
    } 
    vector<T> &get() { 
     return internal_vector; 
    } 

    vector<T> internal_vector; 
}; 

そして、このようにそれを使用します。

fake_vector<int> my_fake_vector(vint,vint_length); 
process(my_fake_vector.get()); 

しかし、私はドンベクトルのbegin \ endを設定する方法は分かりません。この質問は、この最後のパズルまたは新しいハックの少ない解決策fake_vectorの解決策には無期限です。

vector<T>を継承し、それはこのような _M_impl._M_start_M_impl._M_finishだと微調整することにより、あなたはでき
+1

最初の/最後のイテレータのペアを取るために 'func()'をリファクタリングします。 –

+0

@RichardHodges APIはプロジェクトの一部ではありません。 – LyingOnTheSky

+3

代わりに、ベクトル要件をスタックの上位に伝播できますか?つまり、最初は未処理配列を使用しないでください。 – GManNickG

答えて

2

:たとえば

template<typename T> 
struct fake_vector : vector<T> { 
    fake_vector(T *array, size_t array_length) { 
     vector<T>::_M_impl._M_start = array; 
     vector<T>::_M_impl._M_finish = array + array_length; 
    } 
    ~fake_vector() { // let's reset our internal vector so it won't try to deallocate our memory 
     vector<T>::_M_impl._M_start = nullptr; 
     vector<T>::_M_impl._M_finish = nullptr; 
    } 
    vector<T> &get() { 
     return *(vector<T>*)this; 
    } 
}; 

通常の使用:

出力
int x[3] = {1,2,3}; 
fake_vector<int> fake_x(x,3); 
for (auto &p : fake_x) 
    printf("%p = %d\n", &p, p); 
for (int i = 0; i < 3; i++) 
    printf("%p = %d\n", &x[i], x[i]); 

0x7ffeb42406e0 = 1 
0x7ffeb42406e4 = 2 
0x7ffeb42406e8 = 3 
0x7ffeb42406e0 = 1 
0x7ffeb42406e4 = 2 
0x7ffeb42406e8 = 3 

NOTEを:libC++を使用している場合(erroの取得など)その_M_implは宣言されていません)、_M_impl._M_start__begin__M_impl._M_finish__end_に置き換えてみてください。

+2

これは移植性がなく、アンダースコアで始まり大文字で始まる識別子はすべて予約されています。 – Dani

+0

@Dani私はこのためにGCCタグを用意しました。 (これはハックになるだろうと分かっていました)新しい識別子を作成するのではなく、親クラスのメンバーを使用します。 – LyingOnTheSky

+2

これは実際には標準ライブラリの識別子です。それらは、標準ライブラリ実装(libstdC++/libC++/newlib)と、同じgccを持つ標準ライブラリバージョン間で異なる場合があります。 – Dani

関連する問題