当前位置:C++技术网 > 精选 > C/C++编程中的内存管理原则“自己分配自己释放”的总结

C/C++编程中的内存管理原则“自己分配自己释放”的总结

更新时间:2016-12-12 12:03:56浏览次数:1+次

    在无意之中,看到一篇文章《C库中没有itoa以及C++中string没有split方法的原因》,引人思考,所以引用过来供大家阅读思考。

    我的思考的想法先分享一下:

    在C/C++中,内存管理由程序员负责,所以程序员需要谨慎使用内存,否则会出现各种内存错误。这也是程序员头疼的事情,所以很多程序员很畏惧C/C++,不敢学不敢用,因此来讨厌C/C++难用。其实,关键点就是,C/C++是高手玩的转的东西,水平不够的不要喷。

    那么文章《C库中没有itoa以及C++中string没有split方法的原因》给我的启示就是内存的管理问题。文中根据“自己分配自己释放”的内存使用原则来推断了itoa函数和string的split函数不存在的原因,不无道理。在文中的举例说明中,让我突然感觉到内存管理的启发。因为我在之前处理内存的时候,一直在纠结内存的管理关系,要设计一个良好的内存管理的函数。其实就是“自己分配自己释放”,传指针是可以的,只要符合这个原则即可。如果违背这个原则,指针的使用就混乱不堪,而且,指针的传递的层次不要太深,否则一样会随着层次的深入而背离了“自己分配自己释放”的原则。

    下面是引用的文章的信息:


    文章标题:《C库中没有itoa以及C++中string没有split方法的原因》

    引用原文作者:wangdai

    引用原文地址:https://segmentfault.com/a/1190000002643565

    引用原文内容:





    个人见解,欢迎讨论。这其实源于c/c++需要自己管理内存,而一个好的惯例是:自己申请的内存要自己释放掉。
    所以c/c++库函数一般都不会返回指针,你会说有些函数返回指针了呀,如:

char *strcpy (char * __dest, const char * __src);
    但实际返回的是你传入的__dest,内存还是你申请的。另外像一些用c实现的容器会返回指针,比如我们自己实现一个stack可以这样:
typedef struct Stack_T *Stack_T;
void Stack_push(Stack_T stk, void *x);
void *Stack_pop(Stack_T stk);
    但事实上pop出来的void *仍然是你自己push进去的,这个stack并不会帮你生成一个*x的copy,它只存你给它的指针而不是实际的变量。所以这个stack只用自己管理自己的内存,它的内存操作是隐藏在函数内部的,与push和pop对应。
    顺便说一下c++库中stack,和上面这个c版本的有点不太一样,因为c++里存的是变量的值。它的top会返回一个引用即指针,这个指针对应的内存并不是使用者自己申请的,而是在push的时候stack帮你申请的,pop对应地会释放掉它。所以它的top和pop是分开的,否则会产生悬挂指针。
    回到c库中为什么没有itoa,正是因为库函数不能帮你申请一块内存,也就无法返回一个字符串。你说我们可以自己申请内存让库函数把字符串写进去。事实上,sprintf已经做了这个工作。幸运的是,c++11中增加了to_string的函数,我们再也不用自己申请内存再用sprintf了。
    c++也是一样,库函数的返回不能是一个数组(即指针),所以split之后被分开来的多个字符串就无法返回。用vector或者array是可以的,但库中不应该存在这样的依赖关系,即string不应该依赖vector。而在java中,String.split返回的正是一个数组(即指针),这依赖于java强大的垃圾回收机制。