2010-12-05 27 views
1

は、コードのこの部分を考慮してくださいC++ STLコンテナとポインタ有効

Uint counter = 0; 

int* p1; 
int* p2; 

deque<int> dequeInstance; 
vector<int> vectorInstance; 

dequeInstance.push_back(3); 
dequeInstance.push_back(7); 

p1 = &dequeInstance.back(); 

dequeInstance.push_back(17); 

p2 = &dequeInstance.back(); 

if(*p1 == !7) 
    ++counter; 

if(*p2 == !17) 
    ++counter; 

vectorInstance.push_back(3); 
vectorInstance.push_back(7); 

p1 = &vectorInstance.back(); 

vectorInstance.push_back(17); 

p2 = &vectorInstance.back(); 

if(*p1 == !7) 
    ++counter; 

if(*p2 == !17) 
    ++counter; 



return counter; 

私はベクトルの裏面に第三の要素を押し込む際に、第二の要素へのポインタが無効にされたであろうと予想しているであろう私のstd :: vectorの理解は、ワイプされ、変更されるたびに再作成されるストレートな配列です。このコードの最後では、 'counter'はゼロに等しい。

私はここで何が欠けていますか?うまくいけば、パフォーマンスのため

答えて

5

std::vectorは「拭き、それが修正されますたびに再作成」ではありません。

ベクトルは、sizeを超えるかもしれないcapacityを持っています。つまり、実際に使用されているより多くのメモリを割り当てることができます。あなたpush_back新しいサイズが古い容量よりも大きく、この場合で場合、再配分のみ発生します場合は、イテレータは無効化されています。

場合によってはstd::vectorインスタンシエーションの後にcapacityの値をチェックする必要があります。 3より大きい疑いがないことがわかります。したがって、push_back呼び出しのどれも再割り当てをトリガーせず、すべてのイテレーターは有効なままです。

また、std::vectorは、reserveメンバ関数を提供しています。このメンバ関数を使用すると、ベクトルの容量を制御できます。これは、実際の再割り当てを避けるためにいくつの要素が挿入されることが予想されるかを知っているときに本当に便利です。

+1

標準では、 'push_back'の償却された一定時間を保証しています。つまり、毎回「ベクトル」のサイズを変更することはできません。希望はここでは必要ありません:) – fredoverflow

2

[OK]を、あなたはいくつかの問題を抱えています。まず、n = 0でなければ、!n = 0であり、それは1に等しい。したがって、カウンタは決して増加しない。あなたは新しい要素を一backとき

第二のベクターは、必ずしも内容を破壊しません。ベクトルには2つの「サイズ」があります。 1はベクトルの要素数、2は割り当てられたメモリ量です。割り当てられたメモリ量がなくなると、ベクトルは再割り当てされ、コピーされます。

あなたはメモリのエリアを削除した後にさらにメモリが必ずしもクリアされず、まだ有効なデータを指すことがあります。

彼らは無効化され得ることはありませんので、あなたはイテレータを使用していません。あなたはポインタを使用しており、単にメモリ領域を指しています。そのメモリが割り当てられていないという理由だけで、ポインタが無効であることを意味するわけではありません。これは、C/C++があなたに残すことができる主要な危険の1つです。 「未定義の動作」を呼び出す際には、「何の問題も生じないように見える」から「恐ろしいほどクラッシュして危険な方法でオペレーティングシステムをダウンさせる」ことができるように、このようなことをしないでください。

+0

おっと!それが意味された!= =。私は朝に書いたものを再入力していました。私には睡眠が必要だ。 – Tomas

+0

@Tomas:ポインタがまだ有効なデータを指しているか、メモリを指していて、未定義のビヘイビアがあるため、割り付け後も値がメモリに残っているのが見えるため、ヒープに返されました... – Goz

関連する問題