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

发布于 2024-08-07 10:35:17 字数 138 浏览 7 评论 0原文

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

我认为理解这一点的最好方法是理解为什么我无法在地图中存储参考。

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

I understand that references are not pointers, but an alias to an object. However, I still don't understand what exactly this means to me as a programmer, i.e. what are references under the hood?

I think the best way to understand this would be to understand why it is I can't store a reference in a map.

I know I need to stop thinking of references as syntactic suger over pointers, just not sure how to :/

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

七分※倦醒 2024-08-14 10:35:17

按照我的理解,引用是在底层以指针的形式实现的。不能将它们存储在映射中的原因纯粹是语义上的;您必须在创建引用时对其进行初始化,并且此后无法再更改它。这与地图的工作方式并不相符。

They way I understand it, references are implemented as pointers under the hood. The reason why you can't store them in a map is purely semantic; you have to initialize a reference when it's created and you can't change it afterward anymore. This doesn't mesh with the way a map works.

花期渐远 2024-08-14 10:35:17

您应该将引用视为“指向非常量对象的 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,因为赋值存在问题它修改右手操作数。

希望它有帮助:)

You should think of a reference as a 'const pointer to a non-const object':

MyObject& ~~ MyObject * const

Furthermore, a reference can only be built as an alias of something which exists (which is not necessary for a pointer, though advisable apart from NULL). This does not guarantee that the object will stay around (and indeed you might have a core when accessing an object through a reference if it is no more), consider this code:

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

Now, there are two requirements for a STL container:

  • T must be default constructible (a reference is not)
  • T must be assignable (you cannot reset a reference, though you can assign to its referee)

So, in STL containers, you have to use proxys or pointers.

Now, using pointers might prove problematic for memory handling, so you may have to:

DO NOT use auto_ptr, there is a problem with assignment since it modifies the right hand operand.

Hope it helps :)

哭泣的笑容 2024-08-14 10:35:17

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

作为一个例子:

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;

The important difference apart from the syntactic sugar is that references cannot be changed to refer to another object than the one they were initialized with. This is why they cannot be stored in maps or other containers, because containers need to be able to modify the element type they contain.

As an illustration of this:

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;
§普罗旺斯的薰衣草 2024-08-14 10:35:17

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

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

因此您可以使用映射,但很难保证它会被正确使用,但我将其用于小代码(通常是竞争性的)代码

actually you can use references in a map. i don't recommend this for big projects as it might cause weird compilation errors but:

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

so you can use map but it will be difficult to guaranty it will be used correctly, but i used this for small codes (usually competitive) codes

失去的东西太少 2024-08-14 10:35:17

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

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

A container that stores a reference has to initialize all its elements when constructed and therefore is less useful.

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
}

Also, once initialized, the storage for the container elements cannot be changed. s_ will always refer to the storage of s above.

尝蛊 2024-08-14 10:35:17

这篇文章解释了指针是如何在底层实现的 - http://www.codeproject.com/ KB/cpp/References_in_c__.aspx,它也支持塞巴斯蒂安的答案。

This post explains how pointers are implemented under the hood - http://www.codeproject.com/KB/cpp/References_in_c__.aspx, which also supports sebastians answer.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文