繁体   English   中英

在std :: vector迭代器中使用运算符!=时出错

[英]Error using operator != with std::vector iterator

在一些旧代码中,我看到以下内容:

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在这里做什么。 (无论是在这个论坛还是在Google中,我都无法搜索到它,而不会删除星号,因此搜索说明毫无用处。)

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

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

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

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

错误C2678:二进制'!=':找不到带有[_Ty = myClass *]且类型为'std :: vector <_Ty> :: iterator'的左侧操作数(或没有可接受的转换)的运算符

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

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:二进制'=':找不到带有[_Ty = const myClass *]类型为'std :: vector <_Ty> :: const_iterator'(或没有可接受的转换)的右侧操作数的运算符

我不知道它如何与带有运算符!=的vector.end()一起工作,但是对于带有运算符= ...的vector.begin()却是错误的?

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

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

请记住,空格并不重要,因此让您的声明更易于阅读:

const myClass * const * Q

与...相同

const myClass* const *Q

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

声明以从右到左的顺序读取 (请参阅轻松读取复杂的const声明的规则? ),因此该声明基本上说:

“ Q是指向const MyClass对象的const指针的非const指针”

基本上,这意味着值Q本身可被改变(良好用于重复),但的值myClass*指针Q所指向不能被改变,并且myClass正在由所述指向对象myClass*指针也不能更改(只能在其上调用const方法)。

下面的示例将清除您对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()参考

(检查您的myClassMethod函数( (*Q)->myClassMethod(); )),并参考错误C2678:二进制'=':未找到采用'const Recipe'类型的左操作数的运算符(或者没有可接受的转换)

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

实际上,您在两个地方都有const ,但效果有所不同。

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

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

const myClass *const* Q

首先,使它保持一致,然后将每个const放在修改后的位置。 在这种情况下,这意味着仅移动第一个:

myClass const *const* Q

对于这样的声明,我们要从要声明的对象的名称开始,并将“ *”读为“指向a的指针”,因此应将其读为以下内容:

 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();

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM