关于删除C++指针

On deleting C++ pointers

本文关键字:C++ 指针 删除 于删除      更新时间:2023-10-16

好的。。所以这让我很困惑。我正在处理一些遗留的C++代码,我觉得其中的一些部分不安全,但我不能100%确定。这里有一个片段,例如一些有风险的东西。

struct A {
    A() : a_ptr(0) {}
    A(some_type *ptr) : a_ptr(ptr) {}
    const some_type *a_ptr;
};
struct B {
    B() : b_ptr(0) {}
    B(some_type *ptr) : b_ptr(ptr) {}
    const some_type *b_ptr;
};
struct Data {
    Data(...) {//-Stuff that doesn't invole aptr_list or bptr_list;
    }
    ~Data() {
        for(std::vector<A*>::iterator itr = aptr_list.begin(); itr != aptr_list.end() ++itr) {
            delete *itr;
        }
        for(std::vector<B*>::iterator itr = bptr_list.begin(); itr != bptr_list.end() ++itr) {
            delete *itr;
        }
    }
    std::vector<A*> aptr_list;
    std::vector<B*> bptr_list;
private:
    Data(const Data&);
    Data& operator=(const Data&);
};

然后在实现中,我发现:

void some_func(...) {
    //-Inside some function
    Data& d = get_data(...);
    ...
    for(...) {
         some_type *sptr = dynamic_cast<some_type*>(a_source_of_some_type_pointer);
         A* a = new A(sptr);
         B* b = new B(sptr);
         d.aptr_list.push_back(a);
         d.bptr_list.push_back(b);
    }
}

我对在上面的实现中使用相同的指针sptr感到有点不安;当调用Data的析构函数时,这会产生问题吗?另一方面,看起来我们对A*B*有两个new调用,正好有两个delete,所以如果Data中的析构函数不深——也许这就是我需要澄清的地方,那么也许这毕竟是安全的,我的担忧是错的?我确实注意到,例如,结构AB没有定义任何析构函数,所以我希望它不深入。但我不确定这是否意味着他们的指针数据会被释放。一如既往地欣赏专家的真知灼见。

感谢您的时间和兴趣。

AB没有用户定义的析构函数,因此ab内部的任何东西都不会被破坏(除了它所包含的实际内存被释放之外,但由于sptr只是被保存在那里,所以它不是deleted)。[显然,如果AB包含其他类,例如std::stringstd::vector,则该类将被销毁]。

所以,换句话说,你的代码就是这样——ab只保存了sptr的一个副本,但它从未被删除[在这段代码中,如果以后需要删除,那就另当别论了]。

Data::~Data()不会破坏sptr指针。它将只调用A::~A()B::~B()

我不确定你想做什么,但如果你想进行深度破坏,你需要确保你不会释放之前已经被某人释放的内存地址。

这取决于实现需求,但理想情况下,分配对象的用户也应该释放。因此,由于这个sptr是由其他人分配的,如果你释放它,你可能会得到一个悬空的指针。

sptr不归A或B所有,因此这是正确的。

如果我们真的很挑剔,那么代码可能会泄漏。

如果d.aptr_list.push_back()需要并未能保留更多容量,则ab指向的内存将泄漏。

for(...) {
     some_type *sptr = dynamic_cast<some_type*>(a_source_of_some_type_pointer);
     A* a = new A(sptr);          // Allocate memory
     B* b = new B(sptr)           // Allocate memory (and missing semicolon!!)
     d.aptr_list.push_back(a);    // If this fails,
     d.bptr_list.push_back(b);    // or this,
}                                 // then exception is thrown and memory is lost
                                  // (unless you catch the exception and
                                  // perform a delete).

为了安全起见,应该使用像std::unique_ptr这样的智能指针来包裹指针。

您的列表类型应为std::vector<std::unique_ptr<A>>std::vector<std::unique_ptr<B>>

some_func中,代码可以读取如下内容:

some_type *sptr = dynamic_cast<some_type*>(a_source_of_some_type_pointer);
d.aptr_list.push_back(std::unique_ptr<A>(new A(sptr)));
d.bptr_list.push_back(std::unique_ptr<B>(new B(sptr)));