我理解引用不是指针,而是对象的别名。但是作为程序员,这对我具体意味着什么,即引用在底层是什么,我仍然不太清楚。
我认为最好的方法是理解为什么我不能在映射(map)中存储引用。
我知道我需要停止将引用视为指针的语法糖,只是不确定如何做到 :/
我理解引用不是指针,而是对象的别名。但是作为程序员,这对我具体意味着什么,即引用在底层是什么,我仍然不太清楚。
我认为最好的方法是理解为什么我不能在映射(map)中存储引用。
我知道我需要停止将引用视为指针的语法糖,只是不确定如何做到 :/
就我所理解的,引用在底层实现时是作为指针来实现的。你不能将它们存储在映射中的原因纯粹是语义上的;必须在创建引用时初始化,并且之后不能再更改它。这与映射的工作方式不符。
MyObject& ~~ MyObject * const
// 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
MyObject& firstProblem = *((MyObject*)0);
已经是未定义行为了(你没有使用一个有效对象来初始化引用),因此根据 C++ 标准,它可以格式化你的硬盘或者做其他坏事。(有鼻妖恶魔吗?)但这只是一个非常小的问题,除此之外,你的回答非常好。+1 - sbiA 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!!
你可以使用map,但很难保证它被正确地使用。然而,我通常在小型代码(通常是竞赛代码)中使用它。
存储引用的容器在构建时必须初始化其所有元素,因此不太实用。
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 的存储空间。
std::reference_wrapper
。 - baltermia