【问题标题】:dealing with C++/C structures memory freeing处理 C++/C 结构内存释放
【发布时间】:2012-07-20 13:00:43
【问题描述】:

使用后必须释放结构内存吗?我有示例代码:

struct aa 
{
int a;
char * b ;
    aa()
    {
    a=0;
    b= new char[255];
    }
} ;


aa *ss = new aa[3];

void fill()
{
    aa * ssss = new aa;
    aa * sss = new aa;

    sss->a=10;
    ss[0] = *sss;
    cout<<ss[0].a<<"\n";
    ss[1] = *sss;

    cout<<ss[1].a<<"\n";
    cout<<ssss[1].a<<"\n";
}

int _tmain(int argc, _TCHAR* argv[])
{


    fill();
    delete(ss);
}

我必须在fill 的末尾加上delete(ssss) 吗?

我必须删除main末尾的结构数组ss吗?

我必须创建 destruct 还是构造 ss 以释放 *b 内存?

类是一样的逻辑吗?

【问题讨论】:

  • 我对所有事情都说不:使用std::string 表示b,使用std::array(或std::vector)表示ss,使用普通对象表示sssssss .
  • @BenVoigt:有人说是吗?还是您只是在抱怨不必要的括号?
  • @Mike:最终问题是使用delete,其中需要delete[]。额外的括号向我表明,根本原因是有人认为 delete 是一个函数。
  • 除了其他人已经注意到的问题外,还有未定义行为的次要细节。省略一些不相关的代码,我们有:aa * ssss = new aa; [ ... ] cout&lt;&lt;ssss[1].a&lt;&lt;"\n";。如果没有中间代码,问题就很明显了——ssss 指向一个 aa 对象,但您试图将其视为(至少)两个的数组。
  • @cHao:糟糕的建议,IMO。而不是添加一个析构函数(实际上,可能是一个复制构造函数和赋值运算符)只需将aa 定义为:struct aa { int a; char b[255]; };

标签: c++ c


【解决方案1】:

我必须在填充结束时删除(ssss)吗?

是的,您必须删除使用new 创建的任何内容。但是,这里不需要使用new,只需将其设为自动即可:

void fill() {
    aa ssss; // automatically destroyed on exit from the function
}

我必须在 main 的末尾删除 ss 结构数组吗?

是的,但它是一个数组,所以必须作为数组删除:

delete [] ss;
       ^^

但同样,没有理由动态分配它:

aa ss[3]; // automatically destroyed on exit from the program

我必须创建 destruct 还是构造 ss 以释放 *b 内存?

如果您真的想使用原始指针来管理动态数组,那么可以。您还需要考虑复制构造函数和复制赋值运算符(根据Rule of Three),以使该类可以安全使用。或者,使用智能指针或容器为您管理内存:

struct aa 
{
    int a;
    std::vector<char> b ;

    aa() : a(0), b(255) {}
} ;

类是一样的逻辑吗?

是的,规则总是一样的:用new 创建的任何东西都必须用delete 销毁。如果您尽可能避免动态分配,并在确实需要时使用智能指针、容器和其他RAII 类,管理对象会容易得多。

【讨论】:

    【解决方案2】:

    如果您使用new,则必须使用delete 以避免内存泄漏。如果你在栈上声明一个变量,它会在你退出作用域时被自动释放。

    void something();
    {
        aa b = new aa();
        // Do something
        delete b; // You must use delete
    }
    
    void something();
    {
        aa b();
        // Do something
        // You don't have to use delete
    }
    

    在您的特定情况中,并非绝对必须使用delete,因为无论如何程序都会终止,并且所有分配的内存都将被操作系统释放。

    这样做仍然是一个好习惯,以便保持一致(尽管在某些特定情况下您不想这样做,因为释放大量复杂对象可能需要一些时间,从而减慢程序速度终止)。

    无论如何,在 C++ 中使用裸指针并不是一个好主意,因为有许多所谓的智能指针(例如 shared_ptrunique_ptr)负责调用析构函数并在它们运行后释放内存超出范围。

    PS:在你的代码中,你会有内存泄漏,因为aa结构在构造函数中使用new,而在析构函数中没有调用delete

    【讨论】:

    • 不鼓励使用auto_ptr 是有充分理由的。如果使用 c++11,我会建议 unique_ptr,否则使用 shared_ptr 或 boost unique_ptr
    • 是的,很多程序都喜欢在关机时释放每一点内存。虽然我可以理解这种诱惑,但作为用户,我个人更喜欢不必等待几秒钟。
    • ..或者永远,如果某些线程/s被卡住了。我根本无法理解编写不必要代码的诱惑,尤其是那些困难、笨拙、混乱、复杂的不必要代码,需要在每个操作系统/多核环境上进行测试,以确保它仍然可以工作,并且不会向应用程序运行时功能添加任何内容。代码越多,错误越多:(
    【解决方案3】:

    请,请,请释放你的记忆。我不会在这里详细介绍,但看看这个答案: Can a memory block allocated by using operator new/malloc persist beyond end of program execution?

    【讨论】:

      【解决方案4】:

      C/C++ 中的经验法则:

      • 分配给new?使用delete释放内存
      • 分配给malloccallocrealloc?使用free(void*)释放内存

      【讨论】:

        猜你喜欢
        • 2023-03-10
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2023-03-15
        • 2016-06-17
        • 2012-11-15
        • 2017-05-07
        相关资源
        最近更新 更多