【问题标题】:Do reference invalidation guarantees automatically apply to pointers?引用失效保证会自动应用于指针吗?
【发布时间】:2021-01-27 05:11:50
【问题描述】:

考虑以下代码:

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的有效性是否暗示了它?

【问题讨论】:

  • 这个问题可以改写:当左值引用(其固有属性是底层对象的地址可以指向一个左值)时,是否允许对象更改它们的地址应该保持有效。我非常有信心这个问题的答案是否定的,但显然你想要一个更复杂的答案。另请记住,该标准并非没有错误,并且确实会发生歧义和疏忽。
  • 这是一个措辞缺陷。指针没问题。这就是标准的意图,否则我会吃掉我的帽子。继续前进,这里没什么可看的。
  • 另请注意,您引用的问题主要讨论指针与参考,而您关心的是参考与指针
  • @SebastianHoffmann 如果有助于回答问题,我可以以任何等效的方式重新表述问题。对不起,我不明白你的第二条评论。您的意思是在其中使用 iterator 吗?
  • 您希望int *pref = &amp;ref; 有效还是无效? m[0] 返回一个引用,因此获取它的地址(存储在 ptr 中)相当于同样的事情。

标签: c++ pointers reference language-lawyer


【解决方案1】:

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

【讨论】:

    【解决方案2】:

    据我了解,引用不是指针,一个不能替代另一个,无论它们是否相互实现。

    我自己说得再好不过了。

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

    IMO 不能根据意图判断这些问题并假设它必须有效,即使它似乎是一些措辞缺陷。就目前而言,这种行为必须被视为实现定义的。

    您的研究是彻底的,我相信在这方面没有更多工作要做,我也不知道有任何关于此事的缺陷报告,所以 IMO 的方法像往常一样,如果它不在标准中,则无法假设即使看起来不可能有任何其他方式,它也将始终有效,而且看起来确实如此。

    最终,指向变量的指针与变量引用不同,地址运算符与引用运算符不同。

    如果您觉得应该解决这个问题,您可以随时raise the issue yourself

    【讨论】:

      猜你喜欢
      • 2021-12-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-01-15
      • 2011-05-25
      • 1970-01-01
      相关资源
      最近更新 更多