2013-07-23 133 views
1

OK ..所以这让我困惑。我正在处理一些遗留的C++代码部分,我有一种感觉是不安全的,但我不是100%确定的。这里有一个片段,例如有风险的东西。关于删除C++指针

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*和正好两个delete s,所以如果Data中的析构函数不深 - 也许这就是我需要澄清的地方,那么也许这是安全的,毕竟我的关注是错位的?我注意到,例如AB的结构没有定义任何析构函数,所以我希望它不深。但我不确定这是否意味着它们的指针数据将被释放。一如既往地欣赏专家的见解。

谢谢你的时间和兴趣。

回答

2

AB没有一个用户定义的析构函数,所以里面什么也没有ab被破坏(比它拥有被释放出来的实际内存等,但由于sptr只是在那里举行,它是不是被deleted)。 [很明显,如果AB包含其他类别,例如std::stringstd::vector,该类别将被销毁]。

因此,换句话说,你的代码是蛮好喜欢它 - ab仅持有的sptr副本,但它永远不会被删除[在此位的代码,如果它需要以后删除,那是另一回事]。

+0

谢谢,这令人放心。 :-) –

1

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

+0

只要'* sptr'的生命周期包含使用它的'B'和'B'对象的生命周期。 –

+0

的确,但问题是关于调用Data ::〜Data。 – MSalters

+0

谢谢@MSalters:但是什么是正确的呢? –

2

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

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

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

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