2017-12-06 6 views
0

はの問題を可視化を支援するヘルパークラスを作成してみましょう増加しない:は直接のstdに割り当てる::ベクトルを確保した後、エラーをスローしませんが、ベクトルのサイズ

class C 
{ 
int ID = 0; 

public: 
C(const int newID) 
{ 
    ID = newID; 
} 

int getID() 
{ 
    return ID; 
} 
}; 

あなたは空std::vector<C>、その後、予備を作成すると

:ベクトルのインデックス4に

std::vector<C> pack; 
pack.reserve(10); 
printf("pack has %i\n", pack.size()); //will print '0' 

今、あなたがCの新しいインスタンスを割り当てます。それは10個の要素を保持します私は二つのことがここで奇妙なことがわかっ0

1)が代入は、コンパイラ(Visual Studioの2015年、リリースモード)も、リリースモードでエラーをスロー作るべきではないのですか?

2)実際には要素が位置4に格納されているため、ベクトルのサイズがゼロではなく1であるべきではありませんか?

+0

可能重複[ベクトル間の選択::リサイズ()とベクトル::リザーブ()](https://stackoverflow.com/質問/ 7397768 /ベクトル選択とベクター選択の選択 –

+0

@underscore_d私の質問は、その質問と重複することは絶対にありません。ロングショットではありません。私は '予備 'と'サイズ変更'が何をするのかをよく知っています。私の質問は、 'reserve'が呼ばれた後の' at'の振る舞いです。 – blipblop

+0

_ "私の質問は、" at "の動作に関することです_ _長いショットではありません。地球上では '.at()'の振る舞いはどうですか? '.at()'を使用した場合、プログラムは未定義の動作を生成するのではなく、明確なエラーを通知します。とにかく、あなたの質問は '.resize()'以外の特定の方法( '.reserve()'と '' operator [] 'での索引付けが' 'を増やすことができるかどうかを尋ねるためです。 size() '、' .reserve() 'の後の未割り当てポイントへのインデックス付けが可能かどうかを指定します。 '.at()'はあなたに言ったでしょう –

答えて

1

未定義の動作は未定義です。これをオブジェクトのベクトルにすると、予想外の動作がよりはっきりと分かります。

#include <iostream> 
#include <vector> 

struct Foo { 
    int data_ = 3; 
}; 

int main() { 
    std::vector<Foo> foos; 
    foos.reserve(10); 
    std::cout << foos[4].data_; // This probably doesn't output 3. 
} 

ここで、実際にオブジェクトを割り当てていないため、コンストラクタが実行されていないことがわかります。

もう1つの例では、ベクトルが実際に割り当てを開始していないスペースを使用しているため、ベクトルがバッキングメモリを再割り当てする必要がある場合、書き込んだ値はコピーされません。

#include <iostream> 
#include <vector> 

int main() { 
    std::vector<int> foos; 
    foos.reserve(10); 
    foos[4] = 100; 
    foos.reserve(10000000); 
    std::cout << foos[4]; // Probably doesn't print 100. 
} 
+0

あなたの答えをありがとう。しかし、私はそれが私の実際の例をカバーしているとは思わない。あなたのコードでは、あなたは '' foos [4] = Foo() 'のような新しいFooオブジェクトを割り当てません**。そうした場合、それは常に「3」を印刷しますが、ベクトルはゼロのサイズを保持します。コンパイラなしでエラーが発生します。 – blipblop

1

ショート答え:

1)operator[]はあなたが合格した位置を確認するために想定されていないので、例外をスローする理由はありません。デバッグモードではそうするかもしれませんが、リリースではそうはしません(それ以外の場合はパフォーマンスが低下します)。リリースモードでは、コンパイラはあなたが提供するコードがエラー耐性であることを信頼し、コードを速くするためにすべてを行います。

指定された位置posの要素への参照を返します。 いいえ 境界チェックが実行されます。あなたは単にあなたがまだ所有していないメモリをアクセス

http://en.cppreference.com/w/cpp/container/vector/operator_at

)( reserveは、あなたがそれを行うものは、未定義の動作です) resizeではありません。しかし、あなたは vectorに要素を追加したことは一度もなく、バッファーを変更することさえ考えていません。 @Billが示すように、 vectorはあなたのローカル変更をコピーせずにそのバッファを変更することができます。

編集: また、vector::at機能を使用すると、境界チェックのために例外が発生する可能性があります。

ある:pack.at(4) = C(57);は例外

例をスロー:の

https://ideone.com/sXnPzT
関連する問題