为什么我不能在C ++中的`std :: map`中存储引用?

时间:2009-10-09 11:15:02

标签: c++ dictionary reference std stdmap

我知道引用不是指针,而是对象的别名。但是,我仍然不明白这对我作为程序员究竟意味着什么,即引擎盖下的引用是什么?

我认为理解这一点的最好方法是理解为什么我不能在地图中存储引用。

我知道我需要停止将引用视为指针的语法,只是不确定如何:/

6 个答案:

答案 0 :(得分:27)

他们我理解它,引用被实现为引擎盖下的指针。你不能将它们存储在地图中的原因纯粹是语义上的;你必须在创建引用时初始化引用,然后再也不能更改引用。这与地图的工作方式不相符。

答案 1 :(得分:21)

您应该将引用视为'指向非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容器有两个要求:

  • T必须是默认可构造的(参考不是)
  • T必须是可分配的(您不能重置参考,但您可以指定给他的裁判)

因此,在STL容器中,您必须使用代理或指针。

现在,使用指针可能会导致内存处理出现问题,因此您可能需要:

请勿使用 auto_ptr ,因为修改了右侧操作数,因此分配存在问题。

希望有所帮助:)

答案 2 :(得分:7)

除了语法糖之外,重要的区别在于引用不能更改为引用另一个对象而不是它们初始化的对象。这就是为什么它们不能存储在地图或其他容器中,因为容器需要能够修改它们包含的元素类型。

举例说明:

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;

答案 3 :(得分:3)

实际上你可以在地图中使用引用。我不建议大型项目使用它,因为它可能会导致奇怪的编译错误,但是:

    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!!

所以你可以使用地图,但很难保证它会被正确使用,但我用它来代替小代码(通常是竞争对手的代码)

答案 4 :(得分:1)

存储引用的容器具有以在构造时初始化其所有元素,因此不太有用。

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的存储。

答案 5 :(得分:0)

这篇文章解释了如何在引擎盖下实现指针 - http://www.codeproject.com/KB/cpp/References_in_c__.aspx,它也支持sebastians回答。