【问题标题】:What exactly is invalidation of reference/pointer?引用/指针的失效究竟是什么?
【发布时间】:2019-01-15 19:51:46
【问题描述】:

我在标准中找不到指针/引用无效的任何定义。我问是因为我刚刚发现 C++11 禁止字符串的写时复制(COW)。据我了解,如果应用了 COW,那么 p 仍然是一个有效的指针,r 在以下命令之后仍然是一个有效的引用:

std::string s("abc");
std::string s2(s);
char * p = &(s2[0]);
char & r = s2[0];
s2[1] = "B";

只是他们不再指向/引用s2 的第一个字符,而只是指向s 的第一个字符。

在 C++11 标准中,据说非常量 std::basic_string::operator[] 不会使指向字符串元素的指针/引用(以及迭代器)无效。

如果实施了 COW,哪些规则表明上述示例实际上会使 pr 无效?

【问题讨论】:

  • 应该是s2[1] = 'B';char,而不是字符串文字)?你那里的东西不应该编译。
  • 标准只说“可能失效”。

标签: c++ pointers reference language-lawyer invalidation


【解决方案1】:

标准中没有“无效”的定义,因为该术语是从英语继承而来的。这意味着它在英语中的含义:无效的引用/指针不再有效。无法使用。

但是,有些地方明确指出了此约束。例如,将指针左值转换为右值时(在表达式求值期间发生):

[conv.lval/2] 否则,如果泛泛值引用的对象包含无效的指针值(3.7.4.2、3.7.4.3),则行为是实现定义的

我现在找不到引用的措辞,但无论如何,你不能使用对不再存在的东西的引用是不言自明的。

【讨论】:

  • 在我的示例中,引用的字符仍然存在。但我可能明白你的意思。如果s 被破坏,那么pr 都将真正失效,即使它们与s 的定义无关。
  • @DanielLangr 你说它存在,但实现并不向你保证。这就是失效的意思。与 C++ 中的任何其他“可能是,可能不是”场景相同。建议您根据合同而不是机会编写代码。同意在某些情况下,您实际上可以非常确定地知道无效对象实际上仍然存在。但是,这种情况通常是人为的,不能指导一般情况。
  • [conv.lval] 的意思是timsong-cpp.github.io/cppwp/n4659/…,确切的定义,而不是«从英语继承而来的术语...»
【解决方案2】:

例如:

std::string * p_s(new ::std::string("abc"));
std::string s2(*p_s); // shares buffer with p_s
char const & ch1(static_cast<::std::string const &>(*p_s)[0]);
char const & ch2(static_cast<::std::string const &>(s2)[0]); // same as ch1
// CoW, ch2 becomes invalid, but is backed by p_s buffer
char & ch(static_cast<::std::string &>(s2)[0]); // backed by new buffer
// both ch1 and ch2 become invalid
delete p_s;

【讨论】:

    猜你喜欢
    • 2011-05-18
    • 1970-01-01
    • 2014-06-03
    • 2016-01-27
    • 1970-01-01
    • 2014-10-28
    • 2012-08-27
    • 2010-11-12
    相关资源
    最近更新 更多