我知道引用不是指针,而是对象的别名。但是,我仍然不明白这对作为程序员的我到底意味着什么,即引擎盖下的引用是什么?
我认为理解这一点的最好方法是理解为什么我不能在地图中存储参考。
我知道我需要停止将引用视为语法糖而不是指针,只是不知道如何:/
我知道引用不是指针,而是对象的别名。但是,我仍然不明白这对作为程序员的我到底意味着什么,即引擎盖下的引用是什么?
我认为理解这一点的最好方法是理解为什么我不能在地图中存储参考。
我知道我需要停止将引用视为语法糖而不是指针,只是不知道如何:/
他们按照我的理解,引用被实现为引擎盖下的指针。您不能将它们存储在地图中的原因纯粹是语义上的;您必须在创建引用时对其进行初始化,并且以后不能再更改它。这与地图的工作方式不符。
您应该将引用视为“指向非 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 容器有两个要求:
因此,在 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,它也支持塞巴斯蒂安的回答。