cig*_*ien 11 c++ pointers reference language-lawyer
考虑以下代码:
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
Run Code Online (Sandbox Code Playgroud)
对于像 这样的关联容器std::map
,标准说:
insert 和 emplace 成员不应影响迭代器的有效性和对容器的引用,...
这意味着#1
绝对没问题。但是,我不太确定#2
。
十多年前,这个问题已经被提出和回答。
接受的答案说#2
在技术上是不允许的,但在实践中会起作用。
共识答案(赞成票数是接受的答案的两倍多)说#2
是可以的,简单地说,上述标准引用暗示指针也没有失效。
这个问题至少还有六个相对较新的副本,其中大多数都有答案,并且所有人都说没问题#2
,通常是引用上面相同的标准文本。
我不认为这是正确的。据我了解,引用不是指针,一个不能替代另一个,无论它们是否相互实现。作为对比,下面是标准说有关指称在无序关联容器元素,在换汤不换药的有效性:
重新散列使迭代器无效,...,但不会使对元素的指针或引用无效。
这明确地保证了指针的有效性,表明引用的有效性并不自动暗示它。
那么语言说#2
可以吗?它是由 的有效性所暗示的#1
吗?
正如许多评论所说,这可能是一个轻微的标准误用,该标准也暗示了指针。但是,如果你想进入它的语言律师,请考虑:参考不能重新分配(不是标准本身,而是我找到的官方来源:https : //isocpp.org/wiki/faq/references#reseating -参考)。也就是说,一旦引用指向一个对象,该引用将始终指向该对象。正如此处的标准所述:https : //eel.is/c++draft/intro.object,对象在其整个生命周期中占据给定的存储区域。如此处所述:https : //eel.is/c++draft/basic.compound,指针指向其对象的第一个字节的地址。因此,如果引用仍然有效,因为它不能重新分配给另一个对象,它指向的对象还没有结束其生命周期,所以它占用的内存仍然有效并由该对象持有,因此指向的指针到开头那段记忆仍然有效。因此,在 C++ 抽象机的规则内,如标准中所述,指针仍然有效。