我需要有关指针和内存管理的帮助。
我需要存储不同的对象,这些对象都是从同一个基类派生的,并且一直在使用数组来执行此操作,但是当使用不同的对象填充数组时,它会导致分段错误。
当数组中充满了相同派生类型的对象时,我的程序工作正常。当数组填充不同的对象时,它应该通过存储在第一个位置的对象,但是当它切换到输出第二个对象时,它会给我分段错误。我知道这是一个内存访问问题,但我不清楚我应该如何管理依赖于用户输入的可变数量的对象。
THX, NMR
答案 0 :(得分:5)
确保您在堆栈上推送的指针是动态分配的。以下内容将失败:
std::vector<Base*> objects;
void make_one(void)
{
Derived d;
objects.push_back(&d);
}
因为当函数结束时,&d
指向的类将被释放。通过动态分配对象可以缓解这种情况:
std::vector<Base*> objects;
void make_one(void)
{
Derived *d = new Derived;
objects.push_back(d); // a-ok
}
请记住在完成后浏览向量,并在其上调用delete
:
struct deleter
{
template <typename T>
void operator()(T* pObject) const
{
delete pObject;
}
}
std::for_each(objects.begin(), objects.end(), deleter());
如果您可以使用提升,则会有pointer container library为您执行此操作。请注意,您无法使用auto_ptr
并尝试让它为您执行此操作; auto_ptr
的容器效果不佳。
另外,请确保您的基类具有虚拟析构函数:
struct base
{
virtual ~base(void) {} // important!
}
如果不是,则在基类上调用delete
将仅运行基础构造函数,泄漏派生类可能具有的任何资源。通过使其成为虚拟,编译器可以跳转到正确的析构函数。
答案 1 :(得分:1)
我不会发布完整的解决方案,因为您已将问题确定为家庭作业,但我希望我能帮助您解决问题:
数组用于容纳许多大小相同的 。在数组中存储不同对象的问题(即使它们是从相同的基类派生的)是对象可能具有不同的大小。
通过思考指针,你肯定是在正确的轨道上。
修改(以回应评论):
你会看到这样的事情:
BaseClass * array[size];
array[0] = new DerivedClass(...);
array[1] = new OtherDerivedClass(...);
...
这种方法的一个缺陷是没有内置的数组中对象的删除。您必须循环并手动调用delete
:
for (int index = 0; index < size; index++) { delete array[index]; }
答案 2 :(得分:0)
它看起来非常类似于此处提到的问题:Is array of derived same as array of base?。您是否正在创建派生对象数组并尝试访问它,就像它是一个基数组一样?
您可以使用这样的基本指针数组,但请注意,最好使用std::vector<Base*>
而不是原始数组:
class Base
{
public:
virtual ~Base(){}
virtual void f() {std::cout<<"Base::f()\n";}
};
class Derived1: public Base
{
public:
~Derived1(){}
void f(){std::cout<<"Derived1::f()\n";}
};
class Derived2: public Base
{
public:
~Derived2(){}
void f(){std::cout<<"Derived2::f()\n";}
};
void print(Base** p, int count)
{
for(int i = 0; i < count; ++i)
{
(*p)->f();
++p;
}
}
int main()
{
Base b;
Derived1 d1;
Derived2 d2;
Base* arr[3];
arr[0] = &b;
arr[1] = &d1;
arr[2] = &d2;
print(arr, 3);
return 0;
};