#include <iostream>
#include <vector>
using namespace std;
int main(void){
vector<int> v = {1, 2, 3};
auto& it = v.begin();
// 1.
v.begin() += 1;
cout << *(v.begin()); // output is 1
// 2.
cout << *(v.begin()+1); // output is 2
}
Run Code Online (Sandbox Code Playgroud)
上面的代码显示它v.begin() += 1;没有按我的预期工作。我不知道code1和code2之间的实际区别。v.begin() 是左值还是右值?或无?
插入时而it不是v.begin()两种情况都返回 value 2。为什么会发生这样的事情呢?
v.begin() 是左值还是右值?
这是一个右值。
Run Code Online (Sandbox Code Playgroud)auto& it = v.begin();
这是格式错误的,因为对非常量的左值引用不能绑定到右值。
Run Code Online (Sandbox Code Playgroud)v.begin() += 1;
这会将临时迭代器前进到开头,并丢弃结果。
如果目标是不做任何有用的事情,那么它就“有效”。
Run Code Online (Sandbox Code Playgroud)cout << *(v.begin()); // output is 1
这通过迭代器间接到达开始。
Run Code Online (Sandbox Code Playgroud)cout << *(v.begin()+1); // output is 2
这会将迭代器推进到开头,并且不会丢弃结果,而是间接访问结果迭代器。
v.begin() 不能改变吗?那为什么v.begin()+=1代码没有错误呢?
您可以更改函数返回的临时对象。但是对该临时对象的更改不会影响v.begin()将来返回的内容。
是的,v.begin() += 1是对右值的复合赋值。如果您来自 C,您可能会对此感到惊讶,因为您可能已经了解到“只有左值可以是赋值的左手操作数”。但在 C++ 中,这只适用于基本类型,一般不适用于类类型。
为您自己的类定义赋值运算符重载时,使用左值引用限定成员函数可能很有用,这会阻止直接赋值给右值,从而阻止诸如v.begin() += 1.
Ref 限定符后来被添加到标准中(在 C++11 中),因此预先存在的标准库类不能具有这些限定符,因此不幸的是,可以分配标准类型的右值。有人提议添加限定符,但由于担心向后兼容性而没有通过。我不知道为什么,但新标准类的规范也没有合格的赋值运算符。