矢量迭代程序的增量/减量

Increment/Decrement for Vector Iterator

本文关键字:减量 程序 迭代      更新时间:2023-10-16

Nicolai Josuttis的"C++标准库"

第9章:STL迭代器状态:

以下内容可能无法在某些平台上编译:

std::vector <int> coll;
//sort, starting with second element
//- NONPORTABLE version
if (coll.size() > 1){
   std::sort(++coll.begin(),col.end());
}

根据平台的不同,编译++col.begin()可能失败然而,如果使用例如deque而不是向量,编译总是成功的。。。。…实用程序函数next()和prev()随C++11一起提供考虑到代码的可移植性。

有人能解释一下这种行为吗?

我用MINGW gcc 4.6.1,Windows操作系统得到了正确的输出:

std::vector<int> coll ;
for (int i=15; i>=1; i--)
 coll.push_back(i); 
sort(++coll.begin(),coll.end());
Josuttis很好地解释了这个潜在问题的原因:

这个奇怪问题的原因在于向量、array和字符串的迭代器可能被实现为普通指针。对于所有基本数据类型(如指针),都不允许修改临时值。然而,对于结构和类,这样做是允许的。

换句话说,这完全取决于std::vector<int>::iterator是被定义为一个类,还是仅仅是int*typedef。任何一种都是标准允许的,这就是为什么它可能会在某些编译器上引起问题,而在其他编译器上则不会。

调用coll.begin()时,会创建一个右值std::vector<int>::iterator。如果std::vector<int>::iterator是一个具有已实现前缀operator++的类,则允许修改右值,因此它将进行编译。然而,如果std::vector<int>::iterator是指向int的指针的typedef,则它是基本类型的右值,因此可能无法编译。

containerstd::deque时,Josuttis关于++container.begin()总是被定义为行为的说法在技术上是错误的:该标准不能保证container.begin()任何容器类型返回可修改的左值。当他说"总是成功"时,他真正的意思是"在我所知道的每一个实现中,它都成功了",这并不完全是一回事。

公平地说,在C++11之前,类类型的非const对象不可能将其操作限制为左值,但如果你在不久的将来开始看到类不允许对右值进行赋值、递增和递减,以与基本类型保持一致,也不要感到惊讶。

如果vector::begin()的返回值返回一个l-value(本质上是一个重载了++ operator的对象类型),则可以对其执行++。我不认为标准坚持vector::iterator应该这样实现。兼容的C++标准库可以将vector::iterator实现为指针,即对于vector<T>vector<T>::iterator可能是T*,在这种情况下,++操作将不会编译,因为返回值是r值,并且不能递增r值。

您当前使用的C++库将CCD_ 23实现为具有重载++&因此它是有效的。但这并不意味着它是便携的。

试试这个程序

class iter
{
    int * p_;
    public:
    iter(int * p):p_(p) {}
    iter & operator ++()
    {
        ++p_;
        return *this;
    }
};
class A
{
    int * p_;
    public:
    typedef int * iterator;
    typedef iter miterator;
    iterator get()
    {
        return p_;
    }
    miterator ret()
    {
        return miterator(p_);
    }
};

int main(int argc, char **argv)
{
    A a;
    ++a.get(); // Doesn't compile
    A::iterator i = a.get();
    ++i; // compiles
    ++a.ret(); //compiles
}