2016-06-26 13 views
3

私はまず、vectorstringtestと宣言します。それから私はstringHelloWorldを一backとatestreferenceatest[0]の.ANDその後、私は一backをすることができます。しかし、私はaをpush_backの前と後にそれぞれ印刷し、testにプッシュした後にはaが何もなかったことを観察しました。なぜaは何になりませんか?その要素のreference(a)を自分自身にプッシュバックする際に、ベクターはどのように機能しますか? areferencetest[0]ではなくなりましたか?
ありがとうございます。要素の参照を自身にプッシュバックしている間、ベクターはどのように機能しますか?

備考:push_back test[0]の場合、aも何も表示されません。しかしtest[0]はまだ "こんにちは"です。

#include <iostream> 
#include <string> 
#include <vector> 
using namespace std; 
int main() 
{ 
    vector<string> test; 
    test.push_back("Hello"); 
    test.push_back("World"); 
    string& a = test[0]; 
    cout << "1"<< a << "\n"; 
    test.push_back(a);   //or : test.push_back(test[0]); 
    cout << "2"<< a << "\n"; 
} 

Live Demo

出力:

1Hello 
2 

アップデート:私はそれを得た

、以下の回答やコメントへの感謝。私はsizecapacitytestと書いてあり、両方が2であることを観察しました。 test.push_back(a)を実行すると、ベクトルtestは新しいメモリを割り当て、古い要素を新しいメモリにコピーします。従って、a、その古い要素の参照は、未定義となる。

reserveを使用した同様のコードです。 aが未定義になる理由は私の元の質問と同じだと思います。 (私が間違っているなら、私に教えてください。)

#include <iostream> 
#include <string> 
#include <vector> 
using namespace std; 
int main() 
{ 
    vector<string> test; 
    test.push_back("Hello"); 
    test.push_back("World"); 
    string& a = test[0]; 
    cout << "1"<< a << "\n"; 
    cout << "size:" << test.size() << " capacity:" <<test.capacity() <<"\n"; 
    test.reserve(3);  
    cout << "2"<< a << "\n"; 
} 

出力:

1Hello 
size:2 capacity:2 
2 
+4

'push_back'のすべてのイテレータ、ポインタ、およびベクトル要素への参照は無効になります(あなたがテストしなかったいくつかのケースを除いて) –

答えて

6
test.push_back(a);   //or : test.push_back(test[0]); 

testの最後の要素としてaのコピーを追加します。 atestの要素への参照であるという事実はまったく関係ありません。

この呼び出しの後、aは参照がありません。あなたがオンラインで

cout << "2"<< a << "\n"; 

を持っているとして、それを使用すると、未定義の動作の原因です。一方、testの最初の要素への参照を返します。

test[0]これは、aが参照するものとは異なるオブジェクトへの参照になる可能性があります。

+0

ありがとう。しかし、なぜ、 'a'のコピーは' a'を参照してくれるのですか?それはちょうど "コピー"ではないですか?どうしてリファレンス 'a'が未定義になったのですか?' test.push_back(a) 'を' string b = a'に置き換えました。これは私の元の質問のように 'a'を' b'にコピーしないのですか?しかし、 'a'を' b 'にコピーした後、 'a'は未定義ではなく、" Hello "(' test [0] ')です。 –

+2

現在の容量が新しい要素を保持するのに十分でない場合、 'std :: vector :: push_back'はメモリを割り当てる必要があります。それは、古いオブジェクトを新しいメモリにコピー/移動した後に古いメモリを削除します。結果として、古いオブジェクトへの参照は、ぶら下がり参照になる可能性があります。 –

4

vector::push_backstd::vector定義に従ってコンテナへの既存の参照を無効にしたため、string& aが未定義になりました。 http://en.cppreference.com/w/cpp/container/vector/push_backを参照してください。

新しいサイズ()がcapacity()より大きい場合、すべてのイテレータと参照(過去と最後のイテレータを含む)は無効になります。それ以外の場合は、過去のイテレータのみが無効になります。

aをプッシュする前にベクターの容量がわからないため、参照が無効化されていないことを確認できません。これは未定義の動作で、場合によっては動作する可能性がありますが、他の動作では可能です。

関連する問題