我如何访问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 << ...
另一个问题:如果我取消注释我的行,为什么它会在析构函数中给出运行时错误?
答案 0 :(得分:7)
好的,这里有很多问题。
您将myVect
声明为向量的指针。这是不必要的。使用向量的一个主要好处是,您不必担心内存管理,因为vector
为您执行此操作。堆栈分配向量,但在内部它堆分配用于存储它包含的项的内存。
您永远不会初始化指针。您正在调用未定义的行为,因为该指针无效。要初始化指针,请使用new
。您所拥有的只是一个无效的堆栈分配指针,它不指向堆上的vector
。编辑:我刚刚意识到new
已被删除,所以你可以忽略这个。不过,它根本不应该是一个指针。
您正在使用free
解除分配C ++类(您从未分配过以...开头)。别。这不是C,您使用new
和delete
来管理C ++中的内存(必要时!)。 free
不会调用析构函数,它只会释放一大块内存。另一方面,delete
知道如何处理复杂的C ++类型。 从不将new
/ delete
与malloc
/ free
混合。
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
}
答案 1 :(得分:2)
您可以使用*
运算符使用迭代器访问元素:
for(vector<Month>::const_iterator i = myVect->begin(); i != myVect->end(); i++)
{
Month myMonth = *i;
cout << myMonth.name << " " << myMonth.nr_days << endl;
}
此外,您永远不会在代码中分配vector
。您不应该在先前未从free()
收到的指针上使用malloc()
。否则,这是未定义的行为,并且在您调用free()
时可能会发生运行时错误。
试试这个:
vector<Month> *myVect = new vector<Month>;
...
delete myVect;
答案 2 :(得分:1)
如果通过更改:
删除未初始化的指针错误vector<Month> *myVect;
为:
vector<Month> myVect;
然后这将有效。 (一旦定义ostream << Month
)
for(i = 0; i < myVect.size(); i++)
cout << v[i] << " ";
答案 3 :(得分:0)
您有一个指针myVect
,但在使用之前从不为其赋值(打开编译器警告)。你应该做myVect = new vector<Month>()
之类的事情。 (或者不要将其指向并将->
更改为.
)。你的“foreach”实现的其余部分看起来很好。您也可以使用[]
来访问元素。
你释放常量字符串,你没有分配它们,所以你也不需要释放它们。
答案 4 :(得分:0)
您将myVect
声明为指针但从未分配它,这会给您带来很多麻烦。只需删除*
就可以了。
如果你坚持,你可以像使用数组一样使用索引:
for(int i = 0; i < myVect.size(); i++)
{
Month myMonth = myVect[i];
cout << myMonth.name << " " << myMonth.nr_days << endl;
}
虽然我宁愿像你一样使用迭代器 - 只需要一个简单的修复:
Month myMonth = *i;
答案 5 :(得分: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并阅读它。这种方式简单得多。