我喜欢在堆栈上声明变量,尤其是在使用标准容器时。每次避开new
时,都可以避免潜在的内存泄漏。
我也喜欢使用多态,即使用虚函数的类层次结构。但是,似乎这些功能有点不兼容:你做不到:
std::vector<BaseType> vec;
vec.push_back(DerivedType())
或者至少看起来你会失去你所推送的对象的多态性。
那么,有没有办法协调基于堆栈的内存管理和虚函数的使用?
答案 0 :(得分:6)
明显的答案是:
std::vector<BaseType*> vec;
DerivedType d;
vec.push_back(&d);
但可能不是你想要的。 d
和vec
最好同时死亡;如果vec
比d
更长,那么你的指针就会很糟糕。
我认为你真正想要的是像Boost pointer containers:
boost::ptr_vector<BaseType> vec;
vec.push_back(new DerivedType());
所以你不必担心泄漏。指针容器专门用于轻松使用和存储多态对象的任务。
答案 1 :(得分:3)
在这种情况下,您不仅会失去多态性,而是将slice派生类型对象转换为基类型对象。
但你可以改用智能指针。
std::vector<std::tr1::shared_ptr<BaseType> > vec;
vec.push_back(std::tr1::shared_ptr<BaseType>(new DerivedType()));
答案 2 :(得分:2)
当您在堆栈上声明std::vector
变量时 动态内存分配确实发生 ,用于向量的内部数组。但它不一定来自堆。 std::vector
的第二个模板参数默认为std::allocator
,您可以使用自己的自定义参数替换。{/ p>
为了管理多态类型,有boost::smart_ptr
和boost intrusive库这样的工具。
答案 3 :(得分:2)
您可以使用Boost库或POCO C ++库http://www.pocoproject.org中的智能指针实现。
include "Poco/SharedPtr.h"
include "vector.h"
class Base
{
protected:
std::string somestring;
public:
Base()
{
somestring = "Hello";
}
virtual void Method1() {
std::cout << "Method1 " << somestring.c_str() << std::endl;
}
virtual ~Base()
{
std::cout << "Base" << std::endl;
}
};
class Derived : public Base
{
public:
void Method1()
{
std::cout << "overriden Method1 " << somestring.c_str() << std::endl;
}
~Derived()
{
std::cout << "Derived" << std::endl;
}
};
int main()
{
std::vector<Poco::SharedPtr<Base> > someVector;
for (int i = 0; i < 20 ; i++)
{
Poco::SharedPtr<Base> obj = new Base();
Poco::SharedPtr<Derived> dObj = new Derived();
someVector.push_back(obj);
someVector.push_back(dObj);
}
std::vector<Poco::SharedPtr<Base> >::iterator itr = someVector.begin();
for (int i = 0; i < someVector.size(); i++)
{
someVector[i]->Method1();
}
return 0;
}
答案 4 :(得分:1)
如果您的主要兴趣是防止内存泄漏,您可能希望查看智能指针。我建议Boost's Smart Pointers。
答案 5 :(得分:1)
冲突不在多态和(堆或堆栈)分配之间,因为标准容器通常在堆上分配它们的元素。
冲突是在多态和(值或引用)语义之间。多态性需要引用语义带来的附加级别的间接工作,但标准容器具有值语义。
正如其他答案中已经提到的,解决方案是存储其值是对其他对象的引用的对象,其中更简单的是指针。
答案 6 :(得分:0)