本文转载自微信公众号“光城”,作者lightcity。转载本文请联系广诚公众号。0.介绍在C语言中,内存分配分为静态、自动和动态三种。静态变量是嵌入在源文件中的常量,它们没有那么有趣,因为它们的大小已知并且永远不会改变。自动分配可以被认为是堆栈分配——当一个词法块进入时分配空间,当该块退出时释放空间。它最重要的特性与此直接相关。在C99之前,自动分配的变量需要在编译时知道它们的大小。这意味着任何字符串、列表、映射以及从这些派生的任何结构都必须存在于堆上的动态内存中。程序员使用四种基本操作显式分配和释放动态内存:malloc、realloc、calloc和free。前两个不执行任何初始化,内存可能包含碎片。除了自由,他们都可能失败。在这种情况下,它们返回一个空指针,访问这是未定义的行为;在最好的情况下,你的程序会崩溃。在最坏的情况下,您的程序似乎可以工作一段时间,在崩溃前处理垃圾数据。例如:intmain(){char*str=(char*)malloc(7);strcpy(str,"toptal");printf("chararray=\"%s\"@%u\n",str,str);str=(char*)realloc(str,11);strcat(str,".com");printf("chararray=\"%s\"@%u\n",str,str);free(海峡);返回(0);}输出:chararray="toptal"@2762894960chararray="toptal.com"@2762894960虽然代码很简单,但它已经包含了一个反模式和一个有问题的决定。现实生活中,不应该直接写字节数,而是使用sizeof函数。同样,我们将char*数组分配给所需字符串大小的两倍(超过字符串长度的两倍,以解决空终止),这是一个相当昂贵的操作。更复杂的程序可能会构建更大的字符串缓冲区,从而允许字符串大小增加。1.RAII的发明:新希望所有手动管理至少可以说是令人不快的。在80年代中期,BjarneStroustrup为其全新的C++语言发明了一种新范式。他称之为“ResourceAcquisitionIsInitialization”,基本见解是这样的:可以指定对象具有构造函数和析构函数,这些构造函数和析构函数在适当的时候由编译器自动调用,这是管理给定对象内存的好方法,提供了更方便的方法方法。必需的,并且此技术对于非内存资源也很有用。意味着上面的例子在C++中更简洁:intmain(){std::stringstr=std::string("toptal");std::cout<<"stringobject:"<push_back(line);}file_handle.close();returnlines;}intmain(intargc,char*argv[]){//getfilenamefromthefirstargumentstringfile_name(argv[1]);intcount=read_lines_from_file(file_name).size();cout<<"File"<*lines=newvector;这行得通!不幸的是,虽然这看起来很完美,但它仍然有一个缺陷:它会泄漏内存。在C++中,指向堆的指针在不再需要后必须手动删除;否则,一旦最后一个指针超出范围,该内存将变得不可用,并且在进程结束时操作系统管理它之前不会恢复。惯用的现代C++将在此处使用unique_ptr,从而实现所需的行为。当指针超出范围时,它会删除指针指向的对象。然而,这种行为直到C++11才成为语言的一部分。这里,可以直接使用C++11之前的语法,只需要改main:;lines->push_back(line);}file_handle.close();returnlines;}intmain(intargc,char*argv[]){//getfilenamefromthefirstargumentstringfile_name(argv[1]);vector<字符串>*file_lines=read_lines_from_file(file_name);intcount=file_lines->size();deletefile_lines;cout<<"File"<vec;for(autoc:str)vec.push_back(c);//dosomething}当向量被创建时,元素被推入vector,您不必担心为这些元素分配和释放内存。vector使用new为其堆上的元素分配空间,并使用delete释放该空间。作为vector的用户,你不需要关心实现细节,你可以相信vector不会泄漏。在这种情况下,向量是其元素的句柄对象。标准库中使用RAII的其他示例是std::shared_ptr、std::unique_ptr和std::lock_guard。该技术的另一个名称是SBRM,是范围限制资源管理的缩写。现在,我们修改上面的读取文件的例子:(string&file_name){unique_ptr>lines(newvector);stringline;ifstreamfile_handle(file_name.c_str());while(file_handle.good()&&!file_handle.eof()){getline(file_handle,line);lines->push_back(line);}file_handle.close();returnlines;}intmain(intargc,char*argv[]){//getfilenamefromthefirstargumentstringfile_name(argv[1]);intcount=read_lines_from_file(file_name).get()->size();cout<<"File"<