簡體   English   中英

C ++矢量訪問元素

[英]C++ vector accessing elements

如何從myVector訪問元素,就像我對數組一樣( for(i = 0; i < n; i++) cout << v[i] << " ";

我的代碼:

#include <iostream>
#include <vector>
#include <string>
using namespace std;

class Month
{
public:
    char *name;
    int nr_days;
    Month(char* c, int nr) : name(c), nr_days(nr){};
    ~Month() { /* free(name); */}
};

int main()
{
    Month January("January", 31);
    Month February("February", 28);
    Month March("March", 31);
    Month April("April", 30);
    Month May("May", 31);
    Month June("June", 30);
    Month July("July", 31);
    Month August("August", 31);
    Month September("September", 30);
    Month Octomber("Octomber", 31);
    Month November("November", 30);
    Month December("December", 31);

    vector<Month> *myVect = new vector<Month>;
    myVect->push_back(January);
    myVect->push_back(February);
    myVect->push_back(March);
    myVect->push_back(April);
    myVect->push_back(May);
    myVect->push_back(June);
    myVect->push_back(July);
    myVect->push_back(August);
    myVect->push_back(September);
    myVect->push_back(Octomber);
    myVect->push_back(November);
    myVect->push_back(December);

    for(vector<Month>::const_iterator i = myVect->begin(); i != myVect->end(); i++)
    {
        /*
        Month myMonth = i;
        cout << myMonth.name << " " << myMonth.nr_days << endl;
        */
    }

    free(myVect);
    return 0;
}

我想要像foreach算法: foreach(Month in myVect) cout << ...

另一個問題:如果我取消注釋我的行,為什么它會在析構函數中給出運行時錯誤?

好的,這里有很多問題。

  1. 您將myVect聲明為向量的指針。 這是不必要的。 使用向量的一個主要好處是,您不必擔心內存管理,因為vector會為您執行此操作。 堆棧分配向量,但在內部它堆分配用於存儲它包含的項的內存。

  2. 你永遠不會初始化指針。 您正在調用未定義的行為,因為該指針無效。 要初始化指針,請使用new 你所擁有的是一個無效的堆棧分配指針,它不指向堆上的vector 編輯:我剛剛意識到new已被刪除,所以你可以忽略這個。 不過,它根本不應該是一個指針。

  3. 您正在使用free來釋放C ++類(您從未分配過以...開頭)。 別。 這不是C,你使用newdelete來管理C ++中的內存(必要時!)。 free不會調用析構函數,它只會釋放一大塊內存。 另一方面, delete知道如何處理復雜的C ++類型。 切勿new / deletemalloc / free混合使用。

  4. myVect->begin()返回一個const_iterator ,而不是一個T (即,在這種情況下,不是Month對象)。 通過*運算符取消引用迭代器將產生當前的迭代對象,因此:


Month myMonth = *i  // <--- IMPORTANT!

順便說一句,如果你要經常循環遍歷向量,你可能想要輸入typedef來減少冗長,即

typedef vector<Month>::const_iterator cmonth_iter;

現在你可以寫了

for(cmonth_iter i = myVect.Begin(); i != myVect.end(); ++i )
{
    Month m = *i;
    // do stuff with m    
}

您可以使用*運算符使用迭代器訪問元素:

for(vector<Month>::const_iterator i = myVect->begin(); i != myVect->end(); i++)
{
    Month myMonth = *i;
    cout << myMonth.name << " " << myMonth.nr_days << endl;
}

此外,您永遠不會在代碼中分配vector 你不應該在之前沒有從malloc()收到過的指針上使用free() 否則是未定義的行為,並且在調用free()可能會發生運行時錯誤。

試試這個:

vector<Month> *myVect = new vector<Month>;
...
delete myVect;

如果通過更改以下內容刪除了單位指針錯誤:

vector<Month> *myVect;

至:

vector<Month> myVect;

然后這將工作。 (一旦你定義ostream << Month

for(i = 0; i < myVect.size(); i++)
 cout << v[i] << " ";
  1. 你有一個指針myVect ,但在使用之前從不為它賦值(打開編譯器警告)。 你應該做類似myVect = new vector<Month>()事情。 (或者不要使它成為指針並改變->進入. )。 你的“foreach”實現的其余部分看起來很好。 您也可以使用[]訪問元素。

  2. 你釋放常量字符串,你沒有分配它們,所以你也不需要釋放它們。

您將myVect聲明為指針但從未分配它,這會給您帶來很多麻煩。 只要放下*就可以了。

如果你堅持,你可以像使用數組一樣使用索引:

for(int i = 0; i < myVect.size(); i++)
{        
    Month myMonth = myVect[i];
    cout << myMonth.name << " " << myMonth.nr_days << endl;
}

雖然我寧願像你一樣使用迭代器 - 只需要一個簡單的修復:

    Month myMonth = *i;

您可以將箭頭運算符與迭代器一起使用...

for(vector<Month>::const_iterator i = myVect->begin(); i != myVect->end(); i++)
{
    cout << i->name << " " << i->nr_days << endl;
}

另請注意,使用++i而不是i++迭代器更加慣用(原因是i++需要創建一個將被丟棄的迭代器的副本)。

另請注意,您的代碼是UB(未定義的行為),因為您正在使用指向矢量的指針,但您沒有分配它。 順便說一句,在這種情況下使用指針是無意義的,代碼將是正確和簡單的:

vector<Month> myVect;
myVect.push_back(January);
myVect.push_back(February);
...
for(vector<Month>::const_iterator i = myVect.begin(); i != myVect->end(); ++i)
  ...

我的建議也是避免嘗試使用編譯器來學習C ++(這是我想要做的事情)。

C ++功能強大但也很復雜,不幸的是在很多方面都非常不合邏輯和不對稱(由於它的演變歷史)。 除此之外,當你犯了一個錯誤(例如沒有在原始代碼中分配向量)時,你不能指望編譯器幫助你,甚至在運行時程序可能會做任何事情,包括顯然按預期工作(最糟糕的事情) 。 這個組合是致命的。

復雜性,不對稱性和缺乏運行時檢查都使C ++無法通過實驗學習......只需獲得一本好書並閱讀它。 這種方式簡單得多。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM