代码之家  ›  专栏  ›  技术社区  ›  ng5000

我为什么不能在C++中的“STD::MAP”中存储引用?

  •  36
  • ng5000  · 技术社区  · 16 年前

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

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

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

    6 回复  |  直到 7 年前
        1
  •  33
  •   Sebastiaan M    10 年前

        2
  •  31
  •   Matthieu M.    14 年前

    您应该将引用视为“指向非常量对象的常量指针”:

    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
    

    • T必须是默认可构造的(引用不是)

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

    自动检查 ,赋值有问题,因为它修改了右侧操作数。

    希望有帮助:)

        3
  •  8
  •   Martin B    16 年前

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

    为了说明这一点:

    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;
    
        4
  •  7
  •   Eytan    10 年前

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

        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,但很难保证它被正确使用,但我将其用于小代码(通常是竞争性的)代码

        5
  •  2
  •   tcb    12 年前

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

    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
    }
    

    此外,一旦初始化,就不能更改容器元素的存储。斯威尔 总是 请参阅上面的存储。