2012-01-25 73 views
5

如何访问元素从myVector像我将与阵列(for(i = 0; i < n; i++) cout << v[i] << " ";C++向量访问元素

我的代码:

#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 << ...

另一个问题:如果我取消注释我的行,它为什么会在析构函数中给我一个运行时错误?

+0

首先,你可能不想让'myVect'成为一个*指针*,但是如果你这样做了,你需要用new来分配。我很惊讶它不会早点崩溃。 – crashmstr

+0

我在想,“新......”在Adam编辑中被删除了......? – crashmstr

+0

@crashmstr:就是这样。为了羞耻亚当,为了羞耻...... –

回答

7

好吧,这里有很多问题。

  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  
} 
2

您可以访问使用迭代器使用*操作元素:

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; 
1

如果通过更改删除未初始化指针错误:

vector<Month> *myVect; 

到:

vector<Month> myVect; 

,那么这将正常工作。 (一旦你定义ostream << Month

for(i = 0; i < myVect.size(); i++) 
cout << v[i] << " "; 
0
  1. 你有一个指针myVect,但从来没有使用(上转编译器警告)之前将值分配给它。你应该做一些像myVect = new vector<Month>()。 (或者不要使它成为指针并将->更改为.)。其余的“foreach”实现看起来很好。你也可以使用[]来访问元素。

  2. 你可以释放常量字符串,但你没有分配它们,所以你也不需要释放它们。

0

你声明myVect作为指针,但从不分配它,这会给你很多麻烦。只需放下*,你应该没问题。

如果你坚持,你可以使用索引,就像你会与一个数组:

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

虽然我宁愿使用迭代器为你做了 - 只是一个简单的解决方法:

Month myMonth = *i; 
0

您可以使用迭代器箭头操作符...

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++无法通过实验学习......只需获得good book并阅读它。这种方式更简单。