C++ 全栈知识体系C++ 全栈知识体系
✿导航
  • 基础
  • 函数
  • 知识点
  • IO框架
  • 新版本特性
  • 数据库原理
  • SQL语言
  • SQL - MySQL
  • NoSQL - Redis
  • NoSQL - ElasticSearch
  • 算法基础
  • 常见算法
  • 领域算法
  • 分布式算法
  • 数据结构与算法
  • 计算机网络
  • 操作系统
  • 计算机组成
  • 开发
  • 测试
  • 架构基础
  • 分布式系统
  • 微服务
  • 中间件
  • 概念
  • 理论
  • 架构设计原则
  • 设计模式
  • 协议
  • 技术选型
  • 编码规范
  • 流水线构建 - CI/CD
  • 知识点 - Linux
  • 网站 - Nginx
  • 容器化 - Docker
  • 容器编排 - Kubernetes
  • 服务网格 - Service Mesh Istio
  • 常用快捷键 - Shortcut
  • 工具使用 - Tools
  • 开源项目
  • 学习项目
  • 个人项目
  • 项目开发
  • 项目Idea
  • 并发
  • 部署
  • 分布式
  • 知识
  • 问题
  • 编程语言与技术
  • 系统与架构
  • 软件开发实践
  • 数据处理与应用设计
  • 个人
  • 产品
  • 团队
  • 知识体系
  • Vue
关于
✿导航
  • 基础
  • 函数
  • 知识点
  • IO框架
  • 新版本特性
  • 数据库原理
  • SQL语言
  • SQL - MySQL
  • NoSQL - Redis
  • NoSQL - ElasticSearch
  • 算法基础
  • 常见算法
  • 领域算法
  • 分布式算法
  • 数据结构与算法
  • 计算机网络
  • 操作系统
  • 计算机组成
  • 开发
  • 测试
  • 架构基础
  • 分布式系统
  • 微服务
  • 中间件
  • 概念
  • 理论
  • 架构设计原则
  • 设计模式
  • 协议
  • 技术选型
  • 编码规范
  • 流水线构建 - CI/CD
  • 知识点 - Linux
  • 网站 - Nginx
  • 容器化 - Docker
  • 容器编排 - Kubernetes
  • 服务网格 - Service Mesh Istio
  • 常用快捷键 - Shortcut
  • 工具使用 - Tools
  • 开源项目
  • 学习项目
  • 个人项目
  • 项目开发
  • 项目Idea
  • 并发
  • 部署
  • 分布式
  • 知识
  • 问题
  • 编程语言与技术
  • 系统与架构
  • 软件开发实践
  • 数据处理与应用设计
  • 个人
  • 产品
  • 团队
  • 知识体系
  • Vue
关于
  • 编程语言与技术

    • Effective C++: 改善程序与设计的55个具体做法

      • 第2章 - 构造/析构/赋值运算(一)
      • 第2章 - 构造/析构/赋值运算(二)
      • 第2章 - 构造/析构/赋值运算(三)
      • 第3章 - 资源管理
      • 第4章 - 设计与声明(一)
      • 第4章 - 设计与声明(二)
      • 第5章 - 实现(一)
      • 第5章 - 实现(二)
      • 第6章 - 继承与面向对象设计
      • 第7章 - 模板与泛型编程
    • 深度探索C++对象模型

      • 第1章 - 关于对象
      • 第2章 - 构造函数语意学
      • 第3章 - Data 语意学
    • STL源码剖析

      • 第1章 - STL概论和版本简介
      • 第2章 - 空间配置器
      • 第3章 - 迭代器(iterators)概念与traits编程技法(一)
      • 第3章 - 迭代器(iterators)概念与traits编程技法(二)
      • 第4章 - 序列式容器 vector
      • 第4章 - 序列式容器 list
      • 第4章 - 序列式容器 deque
      • 第4章 - 序列式容器 stack和queue
      • 第4章 - 序列式容器 heap
      • 第4章 - 序列式容器 priority_queue
      • 第4章 - 序列式容器 slist
      • 第5章 - 关联式容器 RB-tree
      • 第5章 - 关联式容器 set和map
      • 第5章 - 关联式容器 hashtable
      • 第6章 - 算法
      • 第6章 - 算法之set
      • 第7章 - 仿函数
      • 第8章 - 配接器
  • 系统与架构

    • 深入理解计算机系统

      • 第1章 - 计算机系统漫游
      • 第2章 - 信息的表示和处理
      • 第3章 - 程序的机器级表示
      • 第5章 - 优化程序性能
      • 第6章 - 存储器层次结构
      • 第7章 - 链接
      • 第8章 - 异常控制流
      • 第9章 - 虚拟内存
      • 第10章 - 系统级I/O
      • 第11章 - 网络编程
      • 第12章 - 并发编程
    • 大型网站技术架构——核心原理与案例分析

      • 第1章 - 大型网站架构演化
      • 第2章 - 大型网站架构模式
      • 第3章 - 大型网站核心架构要素
      • 第4章 - 瞬时响应:网站的高性能架构
      • 第5章 - 万无一失:网站的高可用架构
      • 第6章 - 永无止境:网站的伸缩性架构
      • 第7章 - 随需应变:网站的可扩展架构
      • 第8章 - 固若金汤:网站的安全架构
    • 从零开始学架构

      • 架构基础
      • 架构设计原则
      • 高性能架构
      • 高可用架构
    • 程序员的自我修养————链接、装载与库

      • 第1章 - 简介
      • 第2章 - 静态链路
      • 第3章 - 目标文件里有什么
      • 第4章 - 静态链接
      • 第7章 - 动态链接
      • 第8章 - 共享库版本
      • 第10章 - 内存
      • 第11章 - 运行库
      • 第12章 - 系统调用与API
      • 第13章 - 运行库实现
  • 软件开发实践

    • 重构改善既有代码的设计

      • 第1章 - 重构,第一个示例
      • 第2章 - 重构的原则
      • 第3章 - 代码的坏味道
      • 第5章 - 重构列表
      • 第6章 - 重新组织函数
      • 第7章 - 在对象之间搬移特性
      • 第8章 - 重新组织数据
      • 第9章 - 简化条件表达式
      • 第10章 - 简化函数调用
      • 第11章 - 处理概括关系
      • 第12章 - 设计之大型重构
    • 代码大全2

      • 第1章 - 欢迎进入软件构建的世界
      • 第2章 - 用隐喻来更充分地理解软件开发
      • 第3章 - 三思而后行: 前期准备
      • 第4章 - 关键的构建决策
      • 第5章 - 软件构建中的设计
    • Linux多线程服务端编程——使用muduo C++ 网络库

      • Buffer类的设计
      • 设计与实现
      • 定时器与TimerQueue
      • Protobuf网络传输和Protobuf编解码器与消息分发器
      • EventLoop类剖析
      • EventLoopThread和EventLoopThreadPool剖析
      • TCP网络库和核心类
      • Connector剖析
      • TcpClient剖析
      • 学习总结
      • timing wheel
      • 消息广播服务
      • 线程安全的对象生命期管理
  • 数据处理与应用设计

    • 数据密集型应用系统设计

      • 第1章 - 可靠、可扩展与可维护的应用系统
      • 第2章 - 数据模型与查询语言
      • 第3章 - 数据存储与检索
      • 第4章 - 数据编码与演化
      • 第5章 - 数据复制
      • 第6章 - 数据分区
      • 第7章 - 事务

第3章 资源管理

  • 禁止复制
  • 对底层资源使用引用计数法(reference-count)

以对象管理资源

中心思想:把资源放进对象内,便可以依赖C++的析构函数自动调用机制确保资源被释放。

关键点:

  1. 获得资源后立刻放进管理对象。(Resource Acquisition Is Initialization,RAII)

  2. 管理对象运用析构函数确保资源被释放。

class Lock
{
public:
    explict Lock(Mutex* pm)
    : mutexPtr(pm)
    {
        lock(mutexPtr);
    }
    ~Lock()
    {
        unlock(mutexPtr);
    }
private:
    Mutex *mutexPtr;
}

注意事项:

  1. 为防止资源泄漏,请使用RAII对象,它们在构造函数中获取资源并在析构函数中释放资源。

  2. 两个常被使用的RAII classes分别是share_ptr和auto_ptr,前者通常是较佳选择。

在管理资源类中小心copying行为

如果RAII对象被复制,会发生什么情况?

禁止复制

通常允许RAII对象被复制不合理,如果需要禁止copy RAII对象,可以通过将copying操作声明为private(继承Uncopyable类)来禁止copy;

对底层资源使用引用计数法(reference-count)

如果需要保留资源直到资源的最后一个使用者被销毁,可实现引用计数法(shared_ptr)。

class Lock
{
public:
    explict Lock(Mutex* pm)
    : mutexPtr(pm , unlock)
    {
        lock(mutexPtr.get());
    }
    ~Lock()
    {
        unlock(mutexPtr);
    }
private:
    std::tr1::shared_ptr<Mutex> mutexPtr;
}

std::tr1::shared_ptr允许指定删除器,当引用次数为0时调用。

在资源管理类中提供对原始资源的访问

#include <iostream>
#include <memory>

using namespace std;

class MyTest
{
public:
	MyTest()
	:n(0)
	{
		cout<<"MyTest()"<<endl;
	}
	~MyTest()
	{
		cout<<"~MyTest()"<<endl;
	}
	MyTest(const MyTest& m)
	{
		cout<<"copying MyTest"<<endl;
		this->n = m.n;
	}
	void printMyTest(MyTest* m)
	{
		cout<<"printMyTest "<<m->n<<endl;
	}
private:
	int n;
};

int main()
{
	//std::shared_ptr<MyTest> m_test = new MyTest();
	//error: conversion from ‘MyTest*’ to non-scalar type ‘std::shared_ptr<MyTest>’ requested

	std::shared_ptr<MyTest> m_test(new MyTest());
	m_test->printMyTest(m_test.get());
	
    //m_test->printMyTest(m_test);
	//error: cannot convert ‘std::shared_ptr<MyTest>’ to ‘MyTest*’ ,通过get方法获取raw指针
	return 0;
}

执行结果:

[root@192 15]# ./main
MyTest()
printMyTest 0
~MyTest()

成对使用new和delete时要采用相同形式

被删除的指针对象,是单一对象或是对象数组,处理方式不同,对象数据内存布局里会多存储一个记录n,表示数组的大小。

(备注:不要对数组形式做typedef操作,容易产生误操作)

std::string* mystr = new std::string();
std::string* mystrArr = new std::string[100];

delete mystr;
delete [] mystrArr;


typedef std::string strArr[10];
std::string* str = new strArr;

delete str;//出错
delete [] str;//正确

以独立语句将newd对象置入智能指针

processWidget(std::shared_ptr<Widget>(new Widget), priority());

调用processWidget需要经历以下三个步骤:

  1. 调用priority()函数;
  2. 执行 new Widget
  3. 调用std::shared_ptr构造函数

C++编译器以什么样的次序完成上述三个步骤存在弹性。如果执行顺序是213,然后在调用priority的过程中出现异常,那new Widget返回的指针将会遗失,不会存入std::shared_ptr内。 即资源创建和资源被转换为资源管理对象过程中,可能发生异常干扰。因此建议将上述函数调用改为:

std::shared_ptr<Widget> pw(new Widget)
processWidget(pw,priority());

​

Last Updated:
Contributors: klc407073648
Prev
第2章 - 构造/析构/赋值运算(三)
Next
第4章 - 设计与声明(一)