簡體   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