代码之家  ›  专栏  ›  技术社区  ›  static_rtti

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

  •  2
  • static_rtti  · 技术社区  · 16 年前

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

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

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

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

    7 回复  |  直到 15 年前
        1
  •  6
  •   GManNickG    16 年前

    显而易见的答案是:

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

    d vec 最好同时死去;如果 向量 寿命长 D

    我觉得你真正想要的是一种刺激 pointer containers :

    boost::ptr_vector<BaseType> vec;
    vec.push_back(new DerivedType());
    

    所以你不用担心泄密。指针容器是专门为简化多态对象的使用和存储而设计的。

        2
  •  3
  •   Sergey Teplyakov    16 年前

    在这种情况下,你不仅失去了多态性,而且 slice 将派生类型对象转换为基类型对象。

    std::vector<std::tr1::shared_ptr<BaseType> > vec;
    vec.push_back(std::tr1::shared_ptr<BaseType>(new DerivedType()));
    
        3
  •  2
  •   Nikolai Fetissov    16 年前

    当你申报时 std::vector 堆栈上的变量 用于向量的内部数组。但它不一定来自堆。的第二个模板参数 默认为 std::allocator 你可以用自己定制的替换。

    对于管理多态类型,有如下工具 boost::smart_ptr boost intrusive 图书馆。

        4
  •  2
  •   Andrew G    12 年前

    可以使用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;
    }
    
        5
  •  1
  •   Yacoby    16 年前
        6
  •  1
  •   Éric Malenfant    16 年前

    多态性和(值或引用)语义之间存在冲突。多态性需要引用语义带来的附加间接层才能工作,但标准容器具有值语义。

    如其他答案中所述,解决方案是存储其值是对其他对象的引用的对象,其中较简单的是指针。

        7
  •  0
  •   Alexander Poluektov    16 年前

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