在C ++中,是否可以协调基于堆栈的内存管理和多态?

时间:2010-02-09 15:00:12

标签: c++ oop memory-management stack

我喜欢在堆栈上声明变量,尤其是在使用标准容器时。每次避开new时,都可以避免潜在的内存泄漏。

我也喜欢使用多态,即使用虚函数的类层次结构。但是,似乎这些功能有点不兼容:你做不到:

std::vector<BaseType> vec;
vec.push_back(DerivedType())

或者至少看起来你会失去你所推送的对象的多态性。

那么,有没有办法协调基于堆栈的内存管理和虚函数的使用?

7 个答案:

答案 0 :(得分:6)

明显的答案是:

std::vector<BaseType*> vec;
DerivedType d;
vec.push_back(&d);

但可能不是你想要的。 dvec最好同时死亡;如果vecd更长,那么你的指针就会很糟糕。

我认为你真正想要的是像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_ptrboost 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)

智能指针是评论建议的最佳解决方案。

另一种技术 - 如果你主要使用多态来隐藏你的类的实现细节 - 是Pimpl idiom