【问题标题】:Deleting user-defined vectors - C++删除用户定义的向量 - C++
【发布时间】:2010-06-24 20:35:47
【问题描述】:

我有 2 个类,比如 A 和 B。B 类有自己的析构函数。在 A 类中,我有一个指向 B 类对象的指针向量。该向量如下:

vector<B*> vect;

在 A 类的析构函数中,我如何检索内存?如果我循环遍历向量,是否检索每个对象并在每个检索到的对象上使用 delete?我在析构函数中尝试过,但它会出现段错误。

非常欢迎您提供解决此问题的任何帮助。很抱歉,我无法发布代码。

【问题讨论】:

  • 在我们回答这个问题之前。我们必须知道你是如何将东西放入向量中的(对象是用 new 创建的吗(这会引发另一个问题,谁拥有你刚刚创建的对象?))。另一个问题是为什么要将指针放在向量中。该向量旨在获取“对象”的所有权,因此除非您的 B 是多态的,否则将 B 对象(而不是指针)放入向量中可能会更好。

标签: c++ vector stl delete-operator user-defined


【解决方案1】:

如果A拥有vect指向的东西,那么它应该能够deletevect中的每一项。如果这样做时出现段错误,那么您的代码中某处存在错误。

不过,一般来说,最好使用智能指针。 Boost 的 ptr_vectorBoost.Pointer Container 的一部分是为您的特定示例设计的,但简单的 std::vector&lt;std::tr1::shared_ptr&lt;B&gt; &gt; 也可以使用(尽管开销更大且语法更尴尬)。

【讨论】:

    【解决方案2】:

    其他一些帖子指出,您最好使用智能指针而不是指针。如果您出于任何原因必须使用指针,则应先循环删除它们。

    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;
    
    }
    

    这没有问题。

    【讨论】:

      【解决方案3】:

      是的,如果 B* 类型的项目指向在堆上分配的对象,那么对于每个项目,您都应该对其调用 delete。

      【讨论】:

        【解决方案4】:

        是的,您将循环向量并删除每个项目。问题是你忘记了第 42 行的毛巾操作员。

        【讨论】:

        • 呵呵,'问题是你忘记了第 42 行的毛巾操作员。'
        • “你忘记了第 42 行的毛巾操作员”是什么意思?是不是开玩笑?
        • @robin:一个不错的搭便车指南参考 - 不过我更愿意在评论中看到。
        • OP 说他们试图循环向量并删除 A 的析构函数中的每个对象,但遇到了段错误......但他们不会提供代码。所以我使用我的 ESP 能力来发现问题并为他们提供正确的解决方案。
        • @Georg:感谢您的澄清,这让我发疯了。奇怪的是我不记得那句话,也许我应该再读一遍......
        【解决方案5】:

        当您需要管理指针的生命周期时,您希望避免将指针存储在容器中。

        如果这是唯一真正的所有者,并且保证是最后一个清理,那么我会选择

        std::vector<B> vect;
        

        如果您有可能重叠的不同引用和生命周期,那么 shared_ptr 会更好(std::tr1 或 boost 取决于编译器)

        std::vector< boost::shared_ptr<B> > vect;
        

        【讨论】:

          【解决方案6】:

          从您的描述看来,您的 A 类 vect 成员应该拥有 B* 指向的数据的终身所有权。

          我建议将该声明更改为

          vector< std::tr1::shared_ptr<B> > vect;
          

          编辑:用 std::tr1::shared_ptr 替换 auto_ptr

          【讨论】:

          猜你喜欢
          • 2019-05-25
          • 1970-01-01
          • 2019-03-18
          • 2020-12-03
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多