0

我最近了解到成员函数可以是ref-qualified,这让我可以编写

struct S {
    S& operator=(S const&) & // can only be used if the implicit object is an lvalue
    { 
      return *this; 
    }
};

S operator+(S const &, S const &) { 
  return {}; 
}

从而阻止用户做类似的事情

S s{};
s + s = S{}; // error

但是,我看到那std::string的成员operator= 不这样做。所以下面的代码编译没有警告

std::string s;
s + s = s;

有理由允许这样做吗?

如果没有,将来是否可以添加 ref 限定符,或者会以某种方式破坏现有代码?

4

2 回答 2

2

很可能,时机在这个决定中发挥了作用。使用 C++11 将 Ref 限定的成员函数添加到该语言中,而std::string自 C++98 以来一直存在。更改标准库中某些内容的定义并非易事,因为它可能会不必要地破坏现有代码。这不是一个人应该专门研究为什么应该允许这种奇怪的分配的情况(即寻找一个用例)。相反,人们还应该看看为什么不允许这种奇怪的分配(即看看好处,并权衡它们与否则工作代码中断时的潜在痛苦)。这种变化多久会在现实的编码场景中产生影响?

查看评论,对一个提议的用例的反驳是“他们可以[另一种方法]”。是的,他们可以,但如果他们不这样做呢?在最初设计结构时提出替代方案是有成效的 ( std::string)。但是,一旦该结构被广泛使用,您就必须考虑当前不使用替代方案的现有代码。对你可能造成的痛苦有足够的好处吗?这种变化真的会经常发现错误吗?在不会触发另一个警告的情况下,此类错误有多常见?(作为一个例子,在语句的条件中使用赋值而不是相等if很可能已经产生了警告。)这些是语言设计者努力解决的一些问题。

请理解,我并不是说不能进行更改,只是说需要仔细考虑。

于 2020-04-10T14:58:04.827 回答
1

无法确定为什么标准不禁止您提出的行为,但有一些可能的解释:

  1. 它只是 C++11 中的一个忽略。在 C++11 之前,没有 ref-qualified 方法,因此有人忘记了更改标准中的行为。

  2. 保留它是为了向后兼容使用“脏”代码的人,例如:

std::string("a") = "gds";

由于一些奇怪的原因。

关于将来添加这个 - 这是可能的。但首先旧的operator=必须被弃用,然后再被删除,因为它会导致上面的代码无法编译。即使这样,一些编译器也可能会支持它以实现向后标准兼容性

于 2020-04-10T14:49:01.543 回答