如何删除在功能参数中声明新的指针?(How to delete new pointer that d

2019-10-23 06:00发布

我班有把它自己类型的指针作为它的参数成员函数。

当我这样做:

Object* obj1 = new Object();
Object* obj2 = new Object();

obj1->add_child(obj2)

delete obj1;
delete obj2;
obj1 = NULL;
obj2 = NULL;

并运行valgrind ,报告说:

HEAP SUMMARY:
    in use at exit: 72,704 bytes in 1 blocks
  total heap usage: 6 allocs, 5 frees, 73,098 bytes allocated

LEAK SUMMARY:
   definitely lost: 0 bytes in 0 blocks
   indirectly lost: 0 bytes in 0 blocks
     possibly lost: 0 bytes in 0 blocks
   still reachable: 72,704 bytes in 1 blocks
        suppressed: 0 bytes in 0 blocks

我看了一个答案说, still reachable优良,无泄漏。 然后,当我试试这个:

Object* obj = new Object();

obj1->add_child(new Object());

delete obj;
obj = NULL;    

valgrind的报告称:

HEAP SUMMARY:
    in use at exit: 72,877 bytes in 3 blocks
  total heap usage: 6 allocs, 3 frees, 73,098 bytes allocated

LEAK SUMMARY:
   definitely lost: 144 bytes in 1 blocks
   indirectly lost: 29 bytes in 1 blocks
     possibly lost: 0 bytes in 0 blocks
   still reachable: 72,704 bytes in 1 blocks
        suppressed: 0 bytes in 0 blocks

很明显,我没有删除new Object()是作为参数传递指针。 所以,我怎么删除指针?

详细UPDATE

的定义add_child(Object* obj)

void add_child(Object* obj) {

    container.add_child(obj);
}

container是其成员的Object ,其是模板类的一个实例。

Container<Object> container;

Container的定义是:

template<class T>
class Container {
public:
    void add_child(const std::string& key, T* child) {
        childrens.insert(std::pair<std::string,T*>(key, child));
    }
private:
    std::multimap<std::string,T*> childrens;
}

然后,儿童实际上是一个std::multimap

我希望这不会太长只是一个问题。

Answer 1:

你需要做一个明确和一致的选择,谁拥有指针。 如果您决定add_child 取得所有权,那么调用者应该预料到他们并不需要删除传入的指针。如果你决定add_child 不采取所有权,那么调用者保留所有权,并删除指针。

你可以让Object取得所有权,所以它的析构函数删除已添加到它的所有子指针。 那么你的第一个例子应该读

Object* obj1 = new Object();
Object* obj2 = new Object();

obj1->add_child(obj2);

delete obj1; // also deletes obj2 automatically

和你的第二个:

Object* obj = new Object();

obj->add_child(new Object());

delete obj; // automatically deletes the unnamed pointer passed in on previous line

如果你不想Object采取所有权,那么你有一个问题,因为你没有删除的方法new Object()的调用者的上下文。

如果你使用智能指针,管理所有权变得更加容易。 add_child可以采取std::unique_ptr<Object>的参数。

auto obj1 = std::make_unique<Object>();
auto obj2 = std::make_unique<Object>();
obj1->add_child(std::move(obj2)); // obj1 takes ownership
// both pointers automatically deleted at scope exit

auto obj = std::make_unique<Object>();
obj->add_child(std::make_unique<Object>());
// both pointers automatically deleted at scope exit


Answer 2:

一旦函数调用结束后,你不再有指针new创造。 如果你调用的函数不会删除指针,那么你有内存泄漏。



Answer 3:

你仍然可以连接内存块的Valgrind的报告是不是你的错- 这是在GCC 5.1的bug 。

我怎么会想出这样的:

块的大小是非常大的( 72704 ),不符合分配的对象的大小,所以接下来我试图划分7270414429 ,看它是否是这些对象的数组。

但事实并非如此,因为既不72704 ,也不72704-4 ,也不72704-8 (数组,数组+ 32位整数来存储大小,阵列+ 64位整数来存储大小)未除尽。 于是我用Google搜索“ 72,704 still reachable ”,这表明了上述问题。

其他回答者的建议使用智能指针(如std::unique_ptrstd::shared_ptr )是健全的,而且我也推荐使用它们。



文章来源: How to delete new pointer that declared on function parameters?