引用无效保证会自动应用于指针吗?

问题描述

考虑以下代码

std::map<int,int> m;
int &ref = m[0];
int *ptr = &m[0];

m.insert({1,2});

std::cout << ref;   // #1
std::cout << *ptr;  // #2

对于诸如std::map之类的关联容器,标准says

insert和emplace成员不应影响迭代器和对容器的引用的有效性,...

这意味着#1绝对可以。但是,我不确定#2


这个问题已经asked,并在十年前得到了答案。

公认的答案是#2在技术上是不允许的,但实际上可以使用。

共识答案(赞成投票的数量是公认答案的两倍多)表示#2是可以的,只需简单地说上述标准引号也暗示指针也不会失效。

此问题至少还有相对较新的副本,大多数都有答案,并且所有人都说#2没问题,通常是在上面引用相同的标准文本。


我认为这是不正确的。据我了解,引用是 not 指针,并且无论它们是否彼此实现,都不能代替另一个。作为比较,以下是关于在重新哈希处理后对无序关联容器中元素的引用的有效性的标准says

重新哈希会使迭代器...无效,但不会使对元素的指针或引用无效。

这明确保证了指针的有效性,这表明引用的有效性不会自动暗示它。


那么语言说#2可以吗? #1的有效性暗示了这一点吗?

解决方法

正如许多评论所说,这可能是一个轻微的标准错误措词,该标准也暗示了指针。但是,如果您希望使用该语言,请采取以下措施:不能重新分配参考(不是标准本身,而是我发现的官方消息来源:https://isocpp.org/wiki/faq/references#reseating-refs)。也就是说,一旦引用指向一个对象,该引用将始终指向该对象。如此处的标准https://eel.is/c++draft/intro.object所述,对象在其整个生命周期内都占据给定的存储区域。如此处所述:https://eel.is/c++draft/basic.compound,指针指向其对象的第一个字节的地址。因此,如果引用仍然有效,因为无法将其重新分配给另一个对象,则它指向的对象尚未结束其生存期,因此它占用的内存仍然有效并由该对象保存,因此指针指向到该内存的开头仍然有效。因此,按照标准概述,在C ++抽象机的规则内,指针仍然有效。

,

据我所知,引用不是指针,并且无论它们是否彼此实现,都不能代替另一个。

我自己不能说得更好。

那么语言说#2可以吗? #1的有效性暗示了这一点吗?

IMO不能凭意图判断这些问题,并认为它必须起作用,即使这似乎是措辞上的缺陷。就目前而言,这种行为必须被视为实现定义。

您的研究是透彻的,我相信在这方面没有更多要做,我也不知道有关此问题的任何缺陷报告,因此,IMO照例是,如果它不在标准范围之内,则不能假定即使似乎没有其他方法,它也将一直工作,并且确实如此。

最终,指向变量的指针与变量引用不同,并且地址操作符与引用操作符也不相同。

如果您认为应该解决此问题,可以随时raise the issue yourself