☰
UE进阶之路-6
2026/10/28 13:53:16 网站建设 项目流程

E09 RAII + E10 手动内存管理:从自动释放到手动配对

日期:2026-08-27
学习章节:01 C++ 语言基础
摘要:今天完成 E09 RAII 文件读写与 E10 手动 new/delete 练习,理解了资源自动释放与手动配对的区别,并通过 FileGuard 的异常测试代码验证了栈展开时析构自动执行。

今日进度

  • E09-1 到 E09-4:FileGuard、异常安全、禁止拷贝
  • E10-1:new/delete 标量
  • E10-2:故意不 delete,观察内存泄漏
  • E10-3:new[]/delete[] 配对
  • E10-4:改用智能指针

一、RAII 与 FileGuard

RAII 的意思是“资源获取即初始化”:构造函数获取资源,析构函数释放资源。无论正常退出还是异常,析构都会执行,资源不会漏释放。

FileGuard 测试代码:

classFileGuard{public:explicitFileGuard(conststd::string&path):File(path){}~FileGuard(){if(File.is_open()){File.close();}}std::ofstream&Stream(){returnFile;}private:std::ofstream File;};

异常安全测试:

try{FileGuardfile_guard("test.txt");file_guard.Stream()<<"written via FileGuard"<<std::endl;throwstd::runtime_error("simulate failure while holding file");}catch(conststd::exception&e){std::cerr<<"caught: "<<e.what()<<std::endl;}

输出顺序:

FileGuard closed automatically caught: simulate failure while holding file

关键点:throw后先发生栈展开,局部对象file_guard在进入catch之前析构,所以“自动关闭”出现在“caught”前面。

二、堆与栈回顾

栈是局部变量的区域,进入函数分配、离开函数自动释放;堆是动态分配区域,生命周期由代码控制。

intvalue=42;// value 在栈上int*p=newint(42);// p 在栈上,p 指向的 int 在堆上

三、new/delete 配对规则

new->deletenew[]->delete[]

delete arr;对new[]数组是未定义行为。对int数组可能碰巧不崩,因为元素没有析构、底层分配器相似,但换成有析构的类型就会泄漏或崩溃。

int*arr=newint[5];delete[]arr;// 必须 delete[]

四、智能指针与 make_unique

std::unique_ptr<int>p=std::make_unique<int>(42);

推荐用make_unique,而不是把裸new包进智能指针:

UseResource(std::unique_ptr<A>(newA),GetValue());

参数求值顺序不固定,如果GetValue()先抛异常,new A的内存就泄漏了。make_unique内部一次完成分配和包装,没有裸指针悬空窗口。

五、代码片段

intscalar=42;int*pScalar=newint(scalar);deletepScalar;int*arr=newint[5];delete[]arr;std::unique_ptr<int>smart=std::make_unique<int>(42);

六、踩坑与收获

  • delete和delete[]不能混用。
  • “碰巧没崩”不等于“正确”,未定义行为不能依赖。
  • 手动内存管理的核心是“谁分配谁释放”,RAII 和智能指针让这条规则自动成立。

明日计划

  • E11 unique_ptr:唯一所有权、移动、容器、工厂函数

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询