2009-03-11 1 views
14

中間挿入を含む固定配列のデータを操作する必要があります。 memcpyなどを使用するのではなく、私はベクトルを使用したい。私は がベクトル要素をCスタイルの配列に戻したいときに問題があります。 は、ここでは、コードです:
std :: vectorの内容をCスタイルの静的配列に安全にコピーするにはどうすればいいですか?

warning C4996: 'std::_Copy_opt' was declared deprecated 
1>  c:\program files\microsoft visual studio 8\vc\include\xutility(2270) : see  declaration of 'std::_Copy_opt' 
1>  Message: 'You have used a std:: construct that is not safe. See documentation on how to use the Safe Standard C++ Library' 
1>  c:\documents and settings\mhd\my documents\tesvector.cpp(50) : see reference to function template instantiation '_OutIt std::copy<std::_Vector_iterator<_Ty,_Alloc>,BYTE*>(_InIt,_InIt,_OutIt)' being compiled 
1>  with 
1>  [ 
1>   _OutIt=BYTE *, 
1>   _Ty=BYTE, 
1>   _Alloc=std::allocator<BYTE>, 
1>   _InIt=std::_Vector_iterator<BYTE,std::allocator<BYTE>> 
1>  ] 

私はそれを実行すると、私は次の実行時エラーを得た:


    Run-Time Check Failure #2 - Stack around the variable 'myarr' was corrupted. 

void tryvector() 
{ 
    using namespace std; 
    const int MAX_SIZE=16; 
    BYTE myarr[MAX_SIZE]={0xb0,0x45,0x47,0xba,0x11,0x12, 0x4e}; 
    vector<BYTE> myvec (myarr, myarr+MAX_SIZE); 
    vector<BYTE>::iterator it; 

    printf("myarr pre :"); 
    for(int i=0;i<MAX_SIZE;++i){ 
     printf("%02x ", myarr[i]) ; 

    } 

    printf("\nmyvec pre :") 
    for(it=myvec.begin(); it<myvec.end();++it){ 
     cout<<hex<<static_cast<int>(*it)<<" "; 

    } 

    it = myvec.begin()+ 3; 
    myvec.insert(it,0x5f); 
    printf("\nmyvec post:"); 
    for(it=myvec.begin(); it<myvec.end();++it){ 
     cout<<hex<<static_cast<int>(*it)<<" "; 


    } 

    copy(myvec.begin(), myvec.end(), myarr); //??? 
    printf("\nmyarr post:"); 
    for(int i=0;i<MAX_SIZE;++i){ 
     printf("%02x ", myarr[i]) ; 

    } 

} 

私は2005年 対使用していますがここで警告があります

私は上記のコードのように '中間挿入'は が特定のprobであるので、私はリストまたはdequeの代わりにベクトルを使用することに注意してくださいレム。 「最後に挿入する」よりも少なく、「要素のランダムアクセス」 よりも少なくなります。

"C++を使用し、Cスタイルの配列の実装を削除します。 すべての配列の実装にベクトルのみを使用する"はあまり役に立ちません。

ありがとうございました。あなたが行うことができます

+0

単に配列の代わりにベクトル<>を使用しているからといって、memcpy()が起こっていないわけではありません。 vector <>メソッドは理解しやすくなりますが、同じことを行い、大きな配列ではパフォーマンスが低下します。 – slacy

答えて

18

問題は、ベクトルに事を追加しているため、初期化したmyarr配列より多くの要素で終了するということです。

あなたが戻って配列にベクトルをコピーしたい場合は、サイズにそれを必要があります

myvec.resize(MAX_SIZE); 

それとも、あなたが戻ってコピー要素の数を制限できます。

copy(myvec.begin(), myvec.begin()+MAX_SIZE, myarr); 

myarrアレイにすべての要素が含まれているようにするには、MAX_SIZEより大きい値を設定する必要があります。なぜ生の配列ではなくvectorを使用することが推奨されています(vectorは、 。

「似たような答えはしたくありませんが、C++を使用してCスタイルの配列の実装を削除してください」すべての配列の実装にベクトルのみを使用すると、vectorと生の配列を必要とするルーチンに&myvec[0]を渡します。 vectorは、まさにこの理由のために生の配列のようにその要素を連続して格納する必要があります。

「安全でない操作」という警告が表示されるため、Microsoftのコンパイラを使用しています。問題を安全に解決するには、copyの代わりにchecked_copyアルゴリズムを使用することになっています。 Evgeny Lazin indicatesとして、配列のチェックイテレータを作成してchecked_copyアルゴリズムに渡すことができます。

マイクロソフトの拡張機能を必要としないコピーセーフを実現するその他のオプションは、配列のサイズを追跡し、データを安全に配列にコピーするメソッドを提供するクラス(おそらくテンプレート化されている)に配列をラップすることです。 STLSoft's array_proxy templateBoost's boost::arrayのようなものが役に立ちます。一般的に

+0

はい、これは実行時の問題を解決します。 –

+0

これはうまくいくようですが、警告はまだあります。それは大丈夫ですか? – mhd

+0

C++ 11ではstd :: arrayもあります。 –

0

memcpy(myarr, &(myvec)[0], myvec.size()) 

編集:あなたはイテレータを使用してもオフセットを使用していないだけで、」それらにアクセスすることができますので、限り安全性が行くように、thisによると、ベクトルは、メモリの連続したセグメントにデータを格納要素への通常のポインタで。

+0

これは、myvec.size()がmyarrより大きいため、同じ問題が発生します。ベクトルと配列の型を変更した場合、意図したとおりに動作しないという追加の問題があります。 –

+0

はい、コンパイル時の問題のみが修正されます。 –

+0

ベクトルが空の場合は、ベクトルの[0]のアドレスを取ることは安全ではないことにも留意してください。より新しいVC++のランタイムは、このことについて大声で訴えるでしょう(そして正しく、IMHO)。 –

3

、私はあなたがこのような何かことができると思います:

void *myarr; 

if((myarr = malloc(myvec.size() * sizeof myvec[0])) != NULL) 
{ 
    memcpy(myarr, &myvec[0], myvec.size() * sizeof myvec[0]); 
    /* Do stuff with the C-style array for a while 
    . 
    . 
    . 
    */ 
    free(myarr); /* Don't forget handing back the memory when done. */ 
} 

これは、ベクトルの要素、および場所にコピーしたデータを保持する新しいCスタイルの配列を割り当てます。この方法では、サイズを静的に一致させる必要はありません。

もちろん、これは一般的なものなので、C配列にアクセスするためにはvoid *しか与えられないので、型を実際の型(この場合は​​)にキャストするか変更する必要があります。

+0

このようなコードを定期的に書いていますか? –

+0

C++ – codymanix

1

あなたはバインドされた配列を見つけるために、テンプレート引数控除を使用することができます。

template<typename T, size_t N> 
size_t copy(std::vector<T> const& src, T[N] dest) { 
    size_t count = std::min(N, src.size()); 
    std::copy(src.begin(), src.begin()+count, dest); 
    return count; 
} 

電源を入れてチェックされないものについて、Microsoftの警告をオフにします。彼らは、あなたに、移植不可能なコードを書くように促すことを目指しています。

+2

+1でmalloc/freeの代わりにnew/delete []を使用する必要があります。しかし、「あなたには移植不可能なコードを書かせることを強いる」? MSは適合性の高い実装を提供し、オフにしやすいオプションの安全機能を追加しています。 –

+0

標準ではない、警告の「Safe Standard C++ Library」への参照を参照してください。それの背後にあるアイデアはそれほど悪くはありませんが、命名規則に一貫しているはずです。例えば。 stdext :: checked_iterator/is /は正しく指定されています。 – MSalters

関連する問題