参照はポインターではなく、オブジェクトへのエイリアスであることを理解しています。しかし、これがプログラマーとしての私にとって正確に何を意味するのか、つまり、ボンネットの下の参照とは何なのか、まだ理解していません。
これを理解する最善の方法は、参照をマップに保存できない理由を理解することだと思います。
参照をポインタよりも構文上の甘いものと考えるのをやめる必要があることはわかっていますが、どうすればよいかわかりません:/
参照はポインターではなく、オブジェクトへのエイリアスであることを理解しています。しかし、これがプログラマーとしての私にとって正確に何を意味するのか、つまり、ボンネットの下の参照とは何なのか、まだ理解していません。
これを理解する最善の方法は、参照をマップに保存できない理由を理解することだと思います。
参照をポインタよりも構文上の甘いものと考えるのをやめる必要があることはわかっていますが、どうすればよいかわかりません:/
私が理解しているように、参照はボンネットの下のポインターとして実装されています。それらをマップに格納できない理由は、純粋にセマンティックです。作成時に参照を初期化する必要があり、後で変更することはできません。これは、マップの仕組みとは一致しません。
参照は、「非 const オブジェクトへの const ポインター」と考える必要があります。
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 つの要件があります。
そのため、STL コンテナーでは、プロキシまたはポインターを使用する必要があります。
現在、ポインターを使用するとメモリ処理に問題が生じる可能性があるため、次のことが必要になる場合があります。
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__.aspx 、これはセバスチャンの回答もサポートしています。