ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

C++面试必考:智能指针从入门到精通,这篇全解析让你彻底搞定!

C++面试必考:智能指针从入门到精通,这篇全解析让你彻底搞定! C++面试必考:智能指针从入门到精通,这篇全解析让你彻底搞定!面试官:「你了解C++智能指针吗?说说shared_ptr和unique_ptr的区别?」候选人:「……」如果你还在支支吾吾,这篇文章就是为你准备的。一、为什么需要智能指针?在C++中,动态内存管理是每个程序员都绕不开的话题。new和delete是C++分配和释放堆内存的基本方式,但它们有一个致命的问题:一旦忘记delete,内存泄漏就发生了。来看一段经典的"翻车"代码:voidprocessData(){Resource*res=newResource();res-doSomething();if(someCondition){return;// 这里直接返回了,delete 被跳过!}res-doMoreThing();deleteres;// 这行可能永远执行不到}这段代码的问题在于:当someCondition为 true 时,函数提前返回,delete res永远不会被执行。如果doSomething()抛出异常,同样会导致内存泄漏。智能指针的本质:用一个栈上的对象来管理堆上的内存。栈对象的生命周期由编译器自动管理,当栈对象销毁时,自动释放它管理的堆内存。这就是RAII(Resource Acquisition Is Initialization)思想的核心。// 智能指针版本 —— 怎么返回都不会泄漏voidprocessData(){std::unique_ptrResourceres(newResource());res-doSomething();if(someCondition){return;// unique_ptr 自动析构,内存自动释放}res-doMoreThing();// 函数结束,unique_ptr 自动 delete}C++11 引入了三种智能指针,定义在memory头文件中:类型头文件所有权模型核心特点std::unique_ptrmemory独占所有权不能复制,只能移动,零开销std::shared_ptrmemory共享所有权引用计数,可复制,有额外开销std::weak_ptrmemory弱引用不增加引用计数,解决循环引用二、unique_ptr:独占式智能指针2.1 基本用法unique_ptr是最简单、最高效的智能指针。它表示"独占所有权"——同一时间只能有一个unique_ptr拥有某个对象。#includememory#includeiostreamclassWidget{public:Widget(intid):id_(id){std::cout"Widget "id_" 构造\n";}~Widget(){std::cout"Widget "id_" 析构\n";}voidrun()const{std::cout"Widget "id_" 运行中\n";}private:intid_;};intmain(){// 方式1:直接构造(C++11)std::unique_ptrWidgetp1(newWidget(1));// 方式2:make_unique(C++14,推荐!)autop2=std::make_uniqueWidget(2);p1-run();p2-run();// 编译错误!unique_ptr 不能复制// auto p3 = p1; // Error: call to deleted constructor// 正确:移动语义,所有权转移autop3=std::move(p1);// p1 现在为空,p3 拥有 Widget(1)// p1-run(); // 运行时崩溃!p1 已经是 nullptrreturn0;}// 输出:// Widget 1 构造// Widget 2 构造// Widget 1 运行中// Widget 2 运行中// Widget 1 析构 (p3 销毁)// Widget 2 析构 (p2 销毁)2.2 unique_ptr 的关键操作autoptr=std::make_uniqueWidget(1);// 获取裸指针(不转移所有权)Widget*raw=ptr.get();// 释放所有权(返回裸指针,不再管理)Widget*released=ptr.release();// ptr 变为 nullptr// 重置(先删除当前对象,再管理新对象)ptr.reset(newWidget(2));// Widget(1) 被删除ptr.reset();// Widget(2) 被删除,ptr 变为 nullptr// 检查是否为空if(ptr){std::cout"ptr 不为空\n";}// 交换两个 unique_ptrautoptr2=std::make_uniqueWidget(3);ptr.swap(ptr2
返回列表