我有 2 个类,比如 A 和 B。B 类有自己的析构函数。在 A 类中,我有一个指向 B 类对象的指针向量。该向量如下:
vector<B*> vect;
在 A 类的析构函数中,如何检索内存?如果我循环遍历向量,是否检索每个对象并在每个检索到的对象上使用 delete?我在析构函数中尝试过,但它出现了段错误。
非常欢迎解决此问题的任何帮助。很抱歉,我无法发布代码。
我有 2 个类,比如 A 和 B。B 类有自己的析构函数。在 A 类中,我有一个指向 B 类对象的指针向量。该向量如下:
vector<B*> vect;
在 A 类的析构函数中,如何检索内存?如果我循环遍历向量,是否检索每个对象并在每个检索到的对象上使用 delete?我在析构函数中尝试过,但它出现了段错误。
非常欢迎解决此问题的任何帮助。很抱歉,我无法发布代码。
如果 A 拥有 所指向的东西vect
,那么它应该能够拥有delete
内的每一项vect
。如果这样做时出现段错误,那么您的代码中某处有错误。
不过,一般来说,您最好使用智能指针。Boost 的ptr_vector(Boost.Pointer Container的一部分是为您的特定示例而设计的,但一个简单的std::vector<std::tr1::shared_ptr<B> >
也可以工作(尽管有更多的开销和更尴尬的语法)。
是的,如果类型的项目B*
指向在堆上分配的对象,那么对于每个项目,您都应该在其上调用 delete。
其他一些帖子指出,您最好使用智能指针而不是指针。如果您出于任何原因必须使用指针,则应首先在循环中删除它们。
for ( std::vector<B*>::iterator it = vect.begin(); it != vect.end(); ++it)
delete (*it);
vect.clear();
编辑:如果您的程序在析构函数中出现段错误,那么您的代码是错误的。也许您将堆栈元素逐个地址放入向量中,但要删除一个对象,它必须在堆上。
#include <iostream>
#include <vector>
#include <string>
class data {
public:
std::string d;
data(std::string _d) : d(_d) { }
};
class container {
public:
std::vector<data*> c;
container() { c.clear(); }
void add (data *d) { c.push_back(d); }
~container() {
for (std::vector<data*>::iterator it = c.begin(); it != c.end(); ++it)
delete (*it);
c.clear();
}
};
int main (int argc, char* argv[]) {
typedef std::vector<std::string> sVec;
typedef sVec::iterator sVecIter;
std::vector<std::string> cmd (argv+1, argv+argc);
{
container k;
for (sVecIter it = cmd.begin(); it != cmd.end(); ++it)
k.add(new data((*it)));
}
return 0;
}
这没有问题。
是的,您将循环向量并删除每个项目。问题是您忘记了第 42 行的毛巾操作员。
当您需要管理指针的生命周期时,您希望避免将指针存储在容器中。
如果这是一个真正的所有者,并且保证是最后一次清理,那么我会选择
std::vector<B> vect;
如果您有可能重叠的不同引用和生命周期,那么 shared_ptr 会更好(std::tr1 或 boost 取决于编译器)
std::vector< boost::shared_ptr<B> > vect;
根据您的描述,听起来您的 A 类 vect 成员应该拥有 B* 指向的数据的终身所有权。
我建议将该声明更改为
vector< std::tr1::shared_ptr<B> > vect;
编辑:用 std::tr1::shared_ptr 替换 auto_ptr