为什么我分配一个对象本身不能正常工作?

Why my assigning an object itself doesn't work properly?

据我所知,对于不保证其操作数求值顺序的运算符,我们不应多次修改操作数。

这里有我写的这个片段:

int main(){
    std::string s = "hello";
    auto beg = s.begin();
    *beg = *beg++;
    std::cout << s << "  " << *beg << std::endl;
}

为什么我会得到这个输出?

hhllo  h

这个:

*beg = (*beg)++;
std::cout << s << " " << *beg << '\n';

产生此输出:

hello  h

所有这些结果都是正确的。你的误解来自于不知道后缀增量是如何工作的。

*beg = *beg++;

根据 C++ 运算符优先级规则,后缀运算符首先出现。所以这是 *beg = *(beg++).

C++17 强制赋值运算符在计算左侧之前完全计算右侧的所有表达式,包括所有副作用。

后缀迭代器递增左值,但它returns 原始值 的副本。原始值是指向第一个字符的迭代器。所以在评估 beg++ 之后,beg 将改变其位置(因此指向第二个字符)。但是表达式的值是指向第一个的迭代器。

然后取消引用此迭代器,从而返回对第一个字符的引用。

之后,评估lhs。 beg 如前所述,指向第二个字符。所以 *beg 是对第二个字符的引用,它被分配给第一个字符的值。


*beg = (*beg)++;

所以这是反过来的。 *beg 是对第一个字符的引用,然后后缀递增。这意味着 *beg 引用的对象被递增,但是表达式 值是 原始值 的副本。即,增加前的字符:'h'.

然后您将此字符分配给第一个字符,从而覆盖您刚刚递增的内容。

顺便说一句:如果您必须深入了解这个细节才能弄清楚表达式的作用,那么您不应该那样写表达式。避免使用后缀表达式,除非它们在某些方面是绝对必要的。