STL 中迭代器和 v.begin() 方法有什么区别?

kim*_*ims 3 c++

#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。为什么会发生这样的事情呢?

eer*_*ika 5

v.begin() 是左值还是右值?

这是一个右值。

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
Run Code Online (Sandbox Code Playgroud)

这会将迭代器推进到开头,并且不会丢弃结果,而是间接访问结果迭代器。

v.begin() 不能改变吗?那为什么v.begin()+=1代码没有错误呢?

您可以更改函数返回的临时对象。但是对该临时对象的更改不会影响v.begin()将来返回的内容。


是的,v.begin() += 1是对右值的复合赋值。如果您来自 C,您可能会对此感到惊讶,因为您可能已经了解到“只有左值可以是赋值的左手操作数”。但在 C++ 中,这只适用于基本类型,一般不适用于类类型。

为您自己的类定义赋值运算符重载时,使用左值引用限定成员函数可能很有用,这会阻止直接赋值给右值,从而阻止诸如v.begin() += 1.

Ref 限定符后来被添加到标准中(在 C++11 中),因此预先存在的标准库类不能具有这些限定符,因此不幸的是,可以分配标准类型的右值。有人提议添加限定符,但由于担心向后兼容性而没有通过。我不知道为什么,但新标准类的规范也没有合格的赋值运算符。

  • @kims 是的,它的格式不正确。 (2认同)