1

好的..所以这让我很困惑。我正在处理一些我觉得不安全的遗留 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当调用析构函数时,这会产生问题吗?另一方面,看起来我们有两个new调用A*B*恰好两个deletes,所以如果析构函数Data不深 - 也许这就是我需要澄清的地方,那么也许这毕竟是安全的,我的担心是错误的?我确实注意到结构AB例如没有定义任何析构函数,所以我希望它不深。但我不确定这是否意味着他们的指针数据将被释放。一如既往地欣赏专家的见解。

感谢您的时间和兴趣。

4

4 回答 4

2

A并且B没有用户定义的析构函数,因此没有任何 INSIDEa或被b破坏(除了它所持有的实际内存被释放,但由于sptr只是保存在那里,它不是deleted)。[显然,如果AB包含其他类,例如 astd::string或 a std::vector,则该类将被销毁]。

所以,换句话说,你的代码就像它一样 -a并且b只包含 的副本sptr,但它从未被删除[在这段代码中,如果它需要稍后删除,那是另一回事]。

于 2013-07-23T23:23:15.627 回答
2

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

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

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

于 2013-07-23T23:31:51.523 回答
1

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

如果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)));
于 2013-07-23T23:39:26.490 回答
1

sptr不属于 A 或 B,所以这是正确的。

于 2013-07-23T23:22:46.197 回答