成员函数内的内存释放

时间:2017-09-16 09:53:55

标签: c++ c++11 memory

我正在考虑这种情况,不是为了真正的实现,而是为了更好地理解指针是如何工作的。

class foo(){
    foo();
    ~foo();
    void doComplexThings(const std::vector<int*>& v){
        int* copy;
        for(int i = 0; i < v.size(); i++){
           copy = v[i];
           // do some stuffs
        }
    }    
}

main(){
    std::vector<int*> myVector; // suppose we have 100 elements

    doComplexThings(myVector);

    for(int i = 0; i < myVector.size(); i++){
         delete myVector[i];
    }
    myVector.clear();    
}

好的,我知道将v[i]复制到另一个指针中是没有意义的,但我在想:copy做内存泄漏? 执行doComplexThings()后,copy将继续存在并占用堆中的空间?

删除所有元素后,它将继续存在并指向释放的内存?

所以从逻辑上讲,如果我用复杂的对象做这些事情,我将继续用非引用对象占用内存吗?或copy保存在堆栈中,因为我不使用新的?在doComplexThings结束时它会被删除吗?

我有点困惑,谢谢!

3 个答案:

答案 0 :(得分:1)

执行此操作时,堆上没有分配额外的内存:

copy = v[i];

变量copy指向与v[i]相同的地址,但没有分配额外的数组,因此不存在内存泄漏。

处理这种情况的一个更好的方法是避免使用原始指针来支持C ++智能指针或容器:

std::vector<std::vector<int>> myVector;

现在您可以删除删除循环,这对于使用new int[length]分配的数组执行此操作的方式不正确 - 它应该使用delete[]代替:

delete[] myVector[i];

答案 1 :(得分:1)

对于C ++社区中的指针主题存在一些混淆。虽然智能指针已经添加到库中以减轻动态内存分配的问题,但原始指针并不过时。实际上,每当你想要在不拥有它的情况下检查另一个对象时,你应该使用一个引用或原始指针,具体取决于你的需要。如果您不清楚所有权的概念,请将对象视为另一个对象所拥有,如果后者负责事后清理(deleting前者)。

例如,newdelete的大部分用途都应替换为以下内容(为简洁省略std):

{
    auto ptr_to_T = make_unique<T>(//constructor params);
    do_stuff_with_smart_ptr(ptr_to_T);
    do_stuff_with_T(*ptr_to_T);
    do_stuff_with_raw_ptr(ptr_to_T.get());
} // automatic release of memory allocated with make_unique()

请注意,如果T*函数没有保留T*的副本,那么do_stuff_with_T()不需要智能指针的函数,因为它没有&#39 ; t影响对象的生命周期。保证对象在ClassThatNeedsSharedOwnership shared_owner; { auto ptr_to_T = make_shared<T>(//constructor params); shared_owner.set_T(ptr_to_T); // do a lot of stuff } // At this point ptr_to_T is destroyed, but shared_owner might keep the object alive 的返回点之后仍然存活,并且其函数签名表示它不通过获取原始指针来拥有对象。

另一方面,如果您需要将指针传递给允许保留指针并稍后引用它的对象,则不清楚何时需要销毁该对象,最重要的是由谁控制。这是通过共享指针解决的。

int

那么上述因素如何影响您的代码。首先,如果向量应该拥有(保持活动)它指向的unique_ptr<int>,它需要保持shared_ptr<int>int。如果它只是指向由其他东西持有的int*,并且它们保证在向量被销毁之前存活,那么你可以使用delete。在这种情况下,显然永远不需要for (auto copy : v){ // equivalent to your i-indexed loop with copy = v[i]; // as long as you don't need the value of i do_stuff_to_int_ptr(copy); // no delete, we don't own the pointee } ,因为根据定义,您的向量和向量上的函数不负责清理!

最后,通过将循环更改为此(您在帖子中标记的C ++ 11),可以使代码更具可读性:

int

如果某个其他对象持有vector<int*>并释放它们,或者它们在堆栈上但保证在指向它们的{{1}}的整个生命周期中保持活着,则这是唯一的。

答案 2 :(得分:0)

基本上你用C指针来解释问题导致引入C ++唯一和共享指针。如果将已分配指针的向量传递给不透明成员函数,则无法知道该函数是否挂起,因此您不知道是否删除指针。事实上,在你的例子中,你似乎并没有,#34; copy&#34;超出范围。

真正的答案是你根本不应该在C ++中使用分配的指针。 stl向量将作为一个更安全,更易于使用的malloc / new版本。然后你应该把它们传递给const&amp;防止功能改变它们。如果你确实需要一个已分配的指针,请创建一个unique_ptr(),然后你知道unique_ptr()是&#34;所有者&#34;记忆。

相关问题