为什么C++标准库运算符接受右值

Why do the C++ standard library operators accept rvalues?

本文关键字:运算符 C++ 标准 为什么      更新时间:2023-10-16

当我运行以下代码时:

std::string myString = "I'm a string.";
const std::string::iterator &myIterator = ++myString.begin();
char c = *myIterator;
std::cout << c << std::endl;

我得到一个分段错误(使用 O3 优化编译)。我认为这是因为 ++ 运算符返回的是 std::string::iterator & 而不是 std::string::iterator,因此我们得到了对临时的引用。是否有原因不实现这会导致编译错误?即,为什么签名不是以下内容?

std::string::iterator &std::string::iterator::operator++() &;

或者更好的是,为什么规范不需要以下签名,以便我们可以毫无问题地处理右值?

std::string::iterator &std::string::iterator::operator++() &;
std::string::iterator std::string::iterator::operator++() &&;

您发布的代码对我来说似乎是合法的:std::string::iterator myIterator = ++myString.begin();将迭代器引用复制到myIterator中,因此没有对临时的悬而未决的引用。

我的心理调试能力告诉我,你的实际代码有两个问题之一:

  • 您的字符串实际上是空的,即使您认为它包含文本。在这种情况下,++begin()无效。
  • 获取迭代器
  • 副本后,以使迭代器无效的方式更改字符串。

@M.M的评论很有见地。特别是,我的第二个建议将限制库在实现迭代器中的选项,因为迭代器不需要作为右值递增(参考:http://en.cppreference.com/w/cpp/iterator/next),事实上,std::string::iterator 可以实现为 char *,它不能作为右值递增。

选择是否遵循我的第一个建议似乎是一个库实现决策,因为标准规定了迭代器可以做什么,而不是它们不能做什么,以免不必要地限制哪些类型可以充当迭代器。当然,此时,更改实现可能会导致用户代码的重大更改。