4

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() 的编译可能会失败。但是,例如,如果您使用双端队列而不是向量,则编译始终会成功。... ... C++11 提供了实用函数 next() 和 prev() 以考虑代码可移植性。

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

对于 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());
4

3 回答 3

3

Josuttis 很好地解释了这个潜在问题的原因:

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

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

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

于 2013-07-20T16:35:38.723 回答
1

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

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

于 2013-07-20T19:05:37.243 回答
0

++如果它返回一个左值,你可以对它的返回值做vector::begin()- 本质上是一个具有重载的对象类型++ operator。我不认为标准坚持vector::iterator应该如何实施。兼容的 C++ 标准库可以实现vector::iterator为指针 - 即 for vector<T>, vector<T>::iteratormay be T*,在这种情况下 ++ 操作将无法编译,因为返回是一个 r 值并且您不能增加一个 r 值。

您正在使用的 C++ 库当前实现vector::iterator为具有重载的对象,++因此它可以工作。但这并不意味着它是便携的。

试试这个程序

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
}
于 2013-07-20T16:38:33.873 回答