C++ の `std::map` に参照を保存できないのはなぜですか?
-
20-09-2019 - |
質問
参照はポインタではなく、オブジェクトへのエイリアスであることを理解しています。しかし、これがプログラマとしての私にとって正確に何を意味するのか、私はまだ理解していません。内部の参照とは何ですか?
これを理解する最善の方法は、マップに参照を保存できない理由を理解することだと思います。
参照をポインタよりも構文的に優れたものとして考えるのをやめる必要があることはわかっていますが、どうすればよいかわかりません:/
解決
彼らは方法私は参照がボンネットの下にポインタとして実装され、それを理解しています。あなたがマップに保存することができない理由は、純粋にセマンティックです。あなたはそれが作成されます際の基準を初期化する必要があり、あなたはもう、後でそれを変更することはできません。これは、マップが動作する方法と噛み合わない。
他のヒント
参照は「非定数オブジェクトへの定数ポインタ」と考える必要があります。
MyObject& ~~ MyObject * const
さらに、参照は、存在するもののエイリアスとしてのみ構築できます (ポインターには必要ありませんが、NULL は別として推奨されます)。これは、オブジェクトが存在し続けることを保証するものではありません (実際、オブジェクトが存在しない場合、参照を介してオブジェクトにアクセスするときにコアが存在する可能性があります)。次のコードを考慮してください。
// Falsifying a reference
MyObject& firstProblem = *((MyObject*)0);
firstProblem.do(); // undefined behavior
// Referencing something that exists no more
MyObject* anObject = new MyObject;
MyObject& secondProblem = *anObject;
delete anObject;
secondProblem.do(); // undefined behavior
STL コンテナには次の 2 つの要件があります。
- T はデフォルトで構築可能である必要があります (参照は構築可能ではありません)
- T は割り当て可能である必要があります (参照をリセットすることはできませんが、参照先に割り当てることはできます)
したがって、STL コンテナではプロキシまたはポインタを使用する必要があります。
さて、ポインタを使用するとメモリ処理に問題が生じる可能性があるため、次のことが必要になる場合があります。
- スマート ポインターを使用する (boost::shared_ptr 例えば)
- 特殊なコンテナを使用します。 ブーストポインタコンテナライブラリ
使ってはいけません auto_ptr, 、右側のオペランドを変更するため、代入に問題があります。
それが役に立てば幸い :)
シンタックスシュガーから離れて重要な違いは、参照は、彼らがで初期化されたものよりも別のオブジェクトを参照するように変更することができないということです。コンテナは、それらに含まれる要素の種類を変更できるようにする必要がありますので、彼らは、マップまたは他の容器に保存することができない理由はここにあります。
この例示として:
A anObject, anotherObject;
A *pointerToA=&anObject;
A &referenceToA=anObject;
// We can change pointerToA so that it points to a different object
pointerToA=&anotherObject;
// But it is not possible to change what referenceToA points to.
// The following code might look as if it does this... but in fact,
// it assigns anotherObject to whatever referenceToA is referring to.
referenceToA=anotherObject;
// Has the same effect as
// anObject=anotherObject;
実際には、マップ内の参照を使用することができます。それは奇妙なコンパイルエラーを引き起こす可能性があるとして、私は大規模なプロジェクトのためにこれをお勧めしませんが、ます:
map<int, int&> no_prob;
int refered = 666;
no_prob.insert(std::pair<int, int&>(0, refered)); // works
no_prob[5] = 777; //wont compile!!!
//builds default for 5 then assings which is a problem
std::cout << no_prob[0] << std::endl; //still a problem
std::cout << no_prob.at(0) << std::endl; //works!!
あなたはマップを使用することができますが、それは正しく使用されます保証することは困難だろうが、私は(通常は競争力のある)コード
小さなコードのためにこれを使用しての参照を格納容器有するの構築、従ってあまり有用である場合、そのすべての要素を初期化する。
struct container
{
string& s_; // string reference
};
int main()
{
string s { "hello" };
//container {}; // error - object has an uninitialized reference member
container c { s }; // Ok
c.s_ = "bye";
cout << s; // prints bye
}
また、一度初期化され、コンテナ要素の記憶を変更することはできません。 S_意志の常にの上記Sのストレージを参照します。
この記事では、ポインタがボンネットの下に実装されている方法を説明します - のhttp://www.codeproject .COM / KB / CPP / References_in_c __もSEBASTIANS答えをサポートしています。ASPX で、ます。