首页 > 解决方案 > 引用失效保证会自动应用于指针吗?

问题描述

考虑以下代码:

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,标准

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

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


这个问题在十多年前就已经被问及并得到了回答。

接受的答案说#2在技术上是不允许的,但在实践中会起作用。

一致的答案(赞成票的数量是接受的答案的两倍多)说#2是可以的,只需说上面的标准引用暗示指针也不会失效。

这个问题也至少有六个相对较新的副本,其中大多数都有答案,而且他们都说没问题#2,通常是引用上面相同的标准文本。


我不认为这是正确的。据我了解,引用不是指针,一个不能替代另一个,无论它们是否相互实现。作为比较,以下是该标准在重新散列时对无序关联容器中元素的引用有效性的说明

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

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


那么语言说没问题#2吗?它的有效性是否暗示了它#1

标签: c++pointersreferencelanguage-lawyer

解决方案


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


推荐阅读