【问题标题】:Can't delete a heap instance of my custom class (C++)无法删除我的自定义类的堆实例 (C++)
【发布时间】:2015-01-13 20:31:59
【问题描述】:

这是我得到的:

class MyClass {
    int holder;
public:
    MyClass() {
        holder = 5;
    }
};

template<class T>
class First {
    std::vector<T> items;
public:
    First() {
        T* tmp;
        for (int i = 0; i < 20; i++) {
            tmp = new T();
            items.push_back(*tmp);
        }
    };
    ~First() {
        for (int i = 0; i < 20; i++) {
            delete items.at(i);
        }
    };
};

class Second {
    std::vector<std::deque<First<MyClass>>> items;
public:
    Second() {
        std::deque<First<MyClass>>* tmp;
        for (int i = 0; i < 10; i++) {
            tmp = new std::deque<First<MyClass>>;
            items.push_back(*tmp);
        }   
    };
    ~Second() {
        for (int i = 0; i < 10; i++) {
            for (int j = 0; j < items.at(i).size(); j++) {
                delete items.at(i).at(j); // this deletes the "First" instances
            }
            delete items.at(i); // this deletes the deque
        }
    };
};

在我的main 中,我创建了一个Second 的实例并向其中添加First 实例(通过未包含的方法)。在main 的末尾,我删除了Second 的实例,这应该会删除Firstdeques 的所有实例。但是,我收到以下错误:

error: cannot delete expression of type 'value_type' (aka 'MyClass')
error: cannot delete expression of type 'value_type' (aka 'First<MyClass>')
error: cannot delete expression of type 'value_type' (aka 'std::deque<First<MyClass>>')

基本上,我所有的delete 命令都在抛出错误。我在这里想念什么?我需要手动实现一个析构函数,因为我在堆上创建了一堆东西 - 对吗?

【问题讨论】:

  • 为什么不使用智能指针?
  • 在头等舱中,您不需要任何新建或删除。 items.push_back(T()); 足以将新 T 添加到向量中。向量会自动删除它包含的元素。
  • @Marcin 这不是一个好建议,因为应该没有指针。
  • 您正在堆上创建对象,然后将这些对象的 副本 推送到向量中,然后泄漏堆对象,然后尝试删除副本(但这样做错误的)。不要那样做。这是未定义的行为和恶心
  • 该代码相当于:T* t = new T(); T copy = *t; delete copy; ...我希望以这种形式看到它表明它有多么明显的错误。

标签: c++ templates heap-memory destructor


【解决方案1】:

您永远不会存储new 表达式的结果。您的代码应该如下所示:

First() {
    T* tmp;
    for (int i = 0; i < 20; i++) {
        tmp = new T();
        items.push_back(*tmp);
        delete tmp;              // result of "new" is still accessible here
    }
}

~First() { }

或者像这样:

First() {
    for (int i = 0; i < 20; i++) {
        items.push_back(T());
    }
}

或者像这样:

First() : items(20) {}

【讨论】:

  • 好吧,我想我现在明白了。显然你的方式要好得多(不需要堆)。但是,在我将副本推入向量之前,对吗?堆中的对象是否有可能成为不在堆中的结构的“一部分”(我希望我能清楚地问这个问题)。
  • @maxmackie:不。对象由连续的内存块组成,并且具有固定的大小。您当然可以将指向内存其他部分的指针粘贴到对象中,但是只有指针是对象的一部分,而不是指针。
  • 知道了,谢谢。写这篇文章的时候我肯定想得不够多:)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-06-09
  • 2013-02-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多