使用operator!=与std :: vector iterator时出错

时间:2017-11-09 18:26:39

标签: c++ vector

在某些遗留代码中,我看到以下内容:

class myClass : public CObject
{
    DECLARE_DYNAMIC(myClass)

public:
    void myClassMethod() const;
    ....
}
std::vector<const myClass*> vMyClass;
...
for (const myClass *const* Q = vMyClass.begin(); Q != vMyClass.end(); Q++)
        (*Q)->myClassMethod();

我不明白 const 在这里做了些什么。 (我不能在这个论坛或谷歌中搜索它,如果没有星号被剥离,所以搜索解释是没用的。)

我所知道的是,这段代码通常假设vector.begin()返回指针而不是迭代器。所以我尝试将for循环重写为:

std::vector<myClass*>::iterator Q;

for (Q = vMyClass.begin(); Q != vMyClass.end(); Q++)
    (*Q)->myClassMethod();

但是我从Visual Studio 2003 C ++编译器中收到以下错误:

  

错误C2678:二进制'!=':找不到左侧的操作符   'std :: vector&lt; _Ty&gt; :: iterator'类型的操作数(或者没有   使用[_Ty = myClass *]

进行可接受的转换

我不明白这里出了什么问题......在我的代码的另一部分:

std::vector<myOtherClass> vMyOtherClass;
...
std::vector<myOtherClass>::iterator Z;

for (Z = vMyOtherClass.begin(); Z != vMyOtherClass.end(); ++Z)
    ...

这个编译得很干净。任何想法为什么我在vMyClass循环上得到错误或该怎么办?知道 const 正在做什么吗?

新信息

最初,我错误地复制了矢量定义。现在它已修复(上图),我看到迭代器缺少一个const。它应该是:

std::vector<const myClass*>::iterator Q;

但是当我在我的代码中进行此修复时,错误消息从调用vector.end()切换到vector.begin():

  

错误C2679:二进制'=':找不到右侧的操作符   'std :: vector&lt; _Ty&gt; :: const_iterator'类型的操作数(或者没有   [_Ty = const myClass *]

可接受的转换

我不知道它对vector.end()和operator!=有什么用,但是对于带有operator = ...的vector.begin()来说错了??

3 个答案:

答案 0 :(得分:1)

  

我不明白const在这里做了什么。

const适用于左边的东西,除非没有,然后它适用于右边的东西。

请记住,空白并不重要,所以让我们的宣言更容易理解:

const myClass * const * Q

相同
const myClass* const *Q

第一个const适用于myClass,第二个const适用于第一个*

声明按从右到左的顺序阅读(参见Easy rule to read complicated const declarations?),因此该声明基本上说:

&#34; Q是指向const MyClass对象的const指针的非const指针&#34;

基本上,意味着可以更改Q本身的值(适合迭代),但myClass*指向的Q指针的值可以“t {0}}被更改,myClass指针指向的myClass*对象也无法更改(只能调用const个方法)。

答案 1 :(得分:0)

以下示例将清除您对const myClass *const* Q

的疑问
#include <iostream>
using namespace std;

int main(void)
{
    int i = 10;
    int j = 20;
    int *pt = &j;

    /* constant pointer to constant integer */
    const int *const ptr = &i;  

    /* constant pointer to constant poniter */
    const int *const * pptr = &pt;  

    cout<< " Address of i :" << &i << "    Address of J : " << &j <<endl;
    cout<< " value of i :  " << i << "    value of J : " << j << endl;
    cout<<" pptr :   " << pptr << endl;
    cout<<" ptr  :   " << ptr << endl;  // ptr is point to i
    cout<<" *pptr :   " << *pptr << endl; // *pptr is pointing j
    cout<<" *ptr  :   " << *ptr << endl;
    cout<<" **pptr :   " << (*(*pptr)) << endl;

    return 0;
}

输出::

Address of i :0x22fe3c    Address of J : 0x22fe38
value of i :  10    value of J : 20
pptr :   0x22fe30
ptr  :   0x22fe3c
*pptr :   0x22fe38
*ptr  :   10
**pptr :   20

希望你现在清楚。

  

我所知道的是,这段代码通常假设vector.begin()返回指针而不是迭代器

你错了,它会返回一个迭代器。请参阅 vector::begin() reference

(检查您的myClassMethod功能((*Q)->myClassMethod();)) 并参考error C2678: binary '=' : no operator found which takes a left-hand operand of type 'const Recipe' (or there is no acceptable conversion)

我的建议:使用最新的C ++ 11 / C ++ 14功能(如auto,...)。

答案 2 :(得分:0)

您实际上在两个位置有const,效果会有所不同。

for (const myClass *const* Q = vMyClass.begin(); Q != vMyClass.end(); Q++)
     ^^1^^          ^^2^^

首先,让我们将声明与其他声明分开:

const myClass *const* Q

让我们开始使其保持一致,并将每个const置于其修改之后。在这种情况下,这意味着只移动第一个:

myClass const *const* Q

对于这样的声明,我们希望从声明的对象的名称开始,并阅读&#34; *&#34; as&#34;指向&#34;的指针,因此读取如下:

 Q is a pointer to a const pointer to a const myClass

您遇到的问题根本与const无关。你遇到的问题是代码的作者依赖于这样一个事实:在某个特定的库中,std::vector<T>::iterator(显然)实现为指向T的指针。这是允许的,但有一些不良的副作用(例如,这意味着vector<derived>::iterator可以隐式转换为vector<base>::iterator),因此现代实现通常会避免它。

如果你想将这段代码转换成现代的C ++,那么除了这一点之外还有一点 - 你可能想要使用这样的东西:

for (auto Q : vMyClass)
    Q->myClassMethod();