Effective C++ 2e Item6

博客主要讨论C++中执行动态内存分配的类,通常在构造函数用new分配内存,析构函数用delete释放。类维护升级后增加指针成员会带来工作,若析构函数未删除指针会导致内存泄露。还提到删除空指针安全,也可使用智能指针对象代替指针成员。

条款6:析构函数里对指针成员调用delete

大多数情况下,执行动态内存分配的的类都在构造函数里用new分配内存,然后在析构函数里用delete释放内存。最初写这个类的时候当然不难做,你会记得最后对在所有构造函数里分配了内存的所有成员使用delete。

然而,这个类经过维护、升级后,情况就会变得困难了,因为对类的代码进行修改的程序员不一定就是最早写这个类的人。而增加一个指针成员意味着几乎都要进行下面的工作:
    ·在每个构造函数里对指针进行初始化。对于一些构造函数,如果没有内存要分配给指针的话,指针要被初始化为0(即空指针)。
    ·删除现有的内存,通过赋值操作符分配给指针新的内存。
    ·在析构函数里删除指针。

如果在构造函数里忘了初始化某个指针,或者在赋值操作的过程中忘了处理它,问题会出现得很快,很明显,所以在实践中这两个问题不会那么折磨你。但是,如果在析构函数里没有删除指针,它不会表现出很明显的外部症状。相反,它可能只是表现为一点微小的内存泄露,并且不断增长,最后吞噬了你的地址空间,导致程序夭折。因为这种情况经常不那么引人注意,所以每增加一个指针成员到类里时一定要记清楚。

另外,删除空指针是安全的(因为它什么也没做)。所以,在写构造函数,赋值操作符,或其他成员函数时,类的每个指针成员要么指向有效的内存,要么就指向空,那在你的析构函数里你就可以只用简单地delete掉他们,而不用担心他们是不是被new过。

当然对本条款的使用也不要绝对。例如,你当然不会用delete去删除一个没有用new来初始化的指针,而且,就象用智能指针对象时不用劳你去删除一样,你也永远不会去删除一个传递给你的指针。换句话说,除非类成员最初用了new,否则是不用在析构函数里用delete的。

说到智能指针,这里介绍一种避免必须删除指针成员的方法,即把这些成员用智能指针对象来代替,比如C++标准库里的auto_ptr。想知道它是如何工作的,看看条款M9和M10。

<think> 我们参考了用户提供的引用内容,其中提到了内存管理、多线程编程和STL等内容。用户已经学完C++基础语法、STL和多线程,接下来应该学习什么? 根据C++的学习路径,在掌握了这些基础之后,可以继续深入学习以下方向: 1. 深入模板元编程:C++的模板是强大且复杂的特性,学习模板元编程可以提高代码的抽象能力和复用性。 2. 现代C++特性(C++11/14/17/20):学习lambda表达式、智能指针、移动语义、并发库等现代特性。 3. 设计模式:掌握常用的设计模式,提高软件设计能力。 4. 网络编程:学习使用C++进行网络编程,如socket编程,以及网络库(如Boost.Asio)的使用。 5. 系统级编程:包括操作系统相关的API调用、进程管理、文件系统操作等。 6. 性能优化:学习如何分析和优化C++程序的性能,包括内存访问模式、缓存友好设计等。 7. 跨平台开发:了解如何在不同的操作系统(如Windows、Linux)上开发和移植C++程序。 8. 深入学习并发编程:虽然已经学习了多线程,但并发编程还有更多高级主题,如无锁编程、线程池、条件变量等。 我们根据这些方向,为用户推荐接下来的学习内容,并生成相关问题。 </think>在学完C++基础语法、STL和多线程后,建议按照以下路径继续深入学习,这些内容能帮助你构建更专业的C++开发能力: ### 1. 现代C++特性(C++11/14/17/20) ```cpp // 示例:现代C++核心特性 auto lambda = [](auto x) { // C++14泛型lambda return std::make_unique<int>(x*2); // 智能指针 }; std::vector<int> v{1,2,3}; // 初始化列表 for(auto&& item : v) { // 范围for循环 std::cout << item << std::endl; } ``` - **关键特性**:智能指针(`unique_ptr/shared_ptr`)、移动语义、lambda表达式、类型推导(`auto`)、并发库(`<future>`) - **学习资源**:《Effective Modern C++》(Scott Meyers)、cppreference.com ### 2. 内存管理进阶 ```cpp // 智能指针应用场景 class Resource { public: Resource() { std::cout << "资源创建\n"; } ~Resource() { std::cout << "资源释放\n"; } }; auto processResource() { auto res = std::make_shared<Resource>(); // 自动内存管理 return res; // 引用计数管理生命周期 } ``` - **重点内容**: - 智能指针的原理与使用场景 - 自定义内存分配器 - 内存泄漏检测工具(Valgrind、AddressSanitizer) - RAII(资源获取即初始化)设计模式 ### 3. 网络编程(结合多线程) ```cpp // 简易TCP服务器示例 void start_server() { boost::asio::io_context io; tcp::acceptor acceptor(io, tcp::endpoint(tcp::v4(), 8080)); auto handle_connection = [&] { tcp::socket socket(io); acceptor.accept(socket); std::thread(handle_client, std::move(socket)).detach(); }; } ``` - **推荐方向**: - Socket编程基础 - 网络库:Boost.Asio/Poco/libevent - HTTP/TCP协议实现 - 高并发服务器架构 ### 4. 设计模式与架构 ```cpp // 工厂模式示例 class Widget { public: virtual void draw() = 0; static std::unique_ptr<Widget> create(WidgetType type); // 工厂方法 }; ``` - **常用模式**: - 创建型:工厂/单例/建造者 - 结构型:适配器/代理/组合 - 行为型:观察者/策略/命令 - **学习建议**:《设计模式:可复用面向对象软件的基础》 ### 5. 跨平台开发 - **关键技术**: - CMake构建系统 - 平台特定API封装(Windows/Linux/macOS) - 条件编译与宏定义 - 跨平台GUI框架(Qt/WxWidgets) ### 6. 性能优化 ```cpp // 缓存友好设计示例 struct alignas(64) CacheLine { // 64字节对齐 int data[16]; }; ``` - **优化方向**: - CPU缓存机制 - 分支预测优化 - SIMD指令集(AVX/SSE) - 性能分析工具(perf、VTune) ### 7. 项目实践建议 ```mermaid graph LR A[基础语法] --> B[STL容器] B --> C[多线程] C --> D[网络编程] D --> E[设计模式] E --> F[性能优化] F --> G[完整项目] ``` - **项目类型**: - 简易数据库系统 - HTTP服务器 - 实时数据处理系统 - 游戏引擎模块
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值