diff --git a/C++/标准库/12 动态内存.md b/C++/标准库/12 动态内存.md index ee9683e8..e2f34f63 100644 --- a/C++/标准库/12 动态内存.md +++ b/C++/标准库/12 动态内存.md @@ -36,6 +36,7 @@ const int * pci = new const int(1024); * 释放一块非new分配的内存,或者将相同的指针释放多次,行为是未定义。产生错误。 * delete对象之后,指针指向的地址被释放了,指针无效。但是指针依旧保存着原先的地址。编程**悬空指针**。 +> 所有可变长度的容器,都有自己的allcator实现动态内存管理,不需要自己手动申请和释放内存。 ## 1 动态内存与智能指针 > 所以智能指针使用过来做动态内存管理的。普通的局部变量及其指针,不需要智能指针。智能指针是辅助new delete来管理动态内存的。智能指针就是为了解决一下问题。 @@ -62,18 +63,29 @@ const int * pci = new const int(1024); ![](2021-03-06-17-05-19.png) -## 2 动态内存管理shared_ptr +### 智能指针陷阱 +> 智能指针本质上不是个指针,是对动态分配的内存的指针的管理,可以通过get函数得到指向动态内存的普通指针。 + +* 不能使用相同的内置指针初始化多个智能指针 +* 不能delete get()返回的普通指针 +* 不能用get()返回的指针初始化或reset另一个智能指针。 +* 如果使用智能指针管理的资源**不是new分配的内存**,传递给他一个删除器。(new分配的动态内存对应的删除器是delete) + +## 2 动态内存管理shared_ptr ### shared_ptr的操作 ![](2021-03-06-17-06-13.png) + + + ### make_shared申请内存 * 最安全的使用动态内存的方法,调用make_shared标准库函数。在动态内存中分配一个对象,并初始化。返回shared_ptr. ``` shared_ptr pn = make_shared(42); - auto = make_shared(42); + auto pn = make_shared(42); ``` ### shared_ptr拷贝和引用计数 @@ -89,18 +101,31 @@ const int * pci = new const int(1024); * shared_ptr可以使用make_shared创建对象。也可以使用new返回的指针来初始化智能指针。此时不需要delete来释放。 ``` -share_ptr p2(new int(42)); +shared_ptr p2(new int(42)); +shared_ptr p3 = new int{42}; ``` ### shared_ptr的其他方法 - +* shared_ptr的赋值、权限转移和清空。 ![](2021-03-06-17-43-51.png) +* 不能试用get初始化另外一个智能指针,也不能用get为智能指针赋值。 + +* 我们智能使用reset将智能指针指向其他的对象,不能将一个新的对象直接赋值给已经初始化的智能指针。reset函数会更新对象的引用计数,使其指向新的动态内存。 + +``` +shared_ptr = new int; +p = new int(23);//错误,不能直接赋值。 +p.reset(new int(1024));//p指向一个新的对象。 +``` + +### 智能指针和异常 +* 当触发异常后,局部变量在销毁的时候也会正常出发智能指针的销毁。 ## 3 动态内存管理 unique_ptr ![](2021-03-06-17-58-42.png) -* unique_ptr是弱化的shared_ptr。某个时刻只能有一个unique_ptr直线跟一个给定的对象。当unique_ptr被销毁时,它所指向的对象也被销毁。 +* unique_ptr。某个时刻只能有一个unique_ptr只有一个给定的对象。当unique_ptr被销毁时,它所指向的对象也被销毁。 * unique_ptr需要绑定到一个new返回的指针上。直接将指针置为空,指针指向的对象就会被释放。可以使用delete释放unique_ptr -* unique_ptr不支持普通的拷贝和赋值操作。但是可以考别或赋值一个将要被销毁的unique_ptr.例如return unique_ptr。实现控制权转移 +* unique_ptr不支持普通的拷贝和赋值操作。但是可以拷贝或赋值一个将要被销毁的unique_ptr.例如return unique_ptr。实现控制权转移 ``` unique_ptr clone(int p){ return unique_ptr(new int(p)); @@ -131,6 +156,57 @@ if(shared_ptrnp = wp.lock()){ } ``` +### 总结 +> 智能指针的操作包括:初始化、解引用、赋值,reset,get。其中赋值操作是一个特例,其他操作都一致: +> * shared_ptr能在两个智能指针之间赋值。reset可以将智能指针指向新的动态内存对象。不能直接将新的动态内存对象赋值给智能指针。 +> * unique_ptr不能再两个智能指针之间赋值,但可以在即将销毁的智能指针之间赋值。不能直接将新的动态内存对象赋值给智能指针。reset可以将智能指针指向新的动态内存对象。 +> * weak_ptr能将shared_ptr和weak_ptr赋值给weak_ptr;不能将新的动态内存对象赋值给智能指针。reset会将指针置为空。 + + ## 4 动态数组 -## 5 文本查询程序 \ No newline at end of file +### 初始化动态内存数组 +``` +int * pia = new int[10];//默认初始化 +int * pia2= new int[10]();//值初始化 +int * pia3 = new int[10]{1,2,3,4,54,6,7,8,6,5}; +``` +* 申请一个大小为0的动态数组是合法的。直接定义一个大小为0的数组是不合法的。 + +### 释放动态数组 + +delete [] pa; + +### 智能指针和动态数组 + +* unique_ptr动态数组版本 + +``` +unique_ptr up(new int[[10]]); +up.release(); +``` +![](2021-03-06-22-29-22.png) + +## 5 allocator动态内存 + +### 简介 +* new将动态内存分配和对象构造组合在了一起。也就是说,分配动态内存的时候,必须确定这块内存上的对象。 +* allocator能够将内存分配和对象构造分离。 +* 在头文件``中 + +### 操作 +* 主要操作如下 +![](2021-03-06-22-34-11.png) + +``` +allcator alloc; +auto const p = alloc.allocate(n);//分配n个未初始化的string +auto q = p; +alloc.construct(q++);//*q为空字符串 +alloc.construct(q++,10,'c');//*q为cccc +alloc.deallocate(p,n) +``` +### allocator算法 +* 标准库为allocator定义了两个伴随算法。 +![](2021-03-06-22-42-35.png) + diff --git a/C++/标准库/2021-03-06-22-29-22.png b/C++/标准库/2021-03-06-22-29-22.png new file mode 100644 index 00000000..5cdbd9eb Binary files /dev/null and b/C++/标准库/2021-03-06-22-29-22.png differ diff --git a/C++/标准库/2021-03-06-22-34-11.png b/C++/标准库/2021-03-06-22-34-11.png new file mode 100644 index 00000000..c504dc67 Binary files /dev/null and b/C++/标准库/2021-03-06-22-34-11.png differ diff --git a/C++/标准库/2021-03-06-22-42-35.png b/C++/标准库/2021-03-06-22-42-35.png new file mode 100644 index 00000000..b8c687ca Binary files /dev/null and b/C++/标准库/2021-03-06-22-42-35.png differ diff --git a/C++/类设计者的工具/1 拷贝控制.md b/C++/类设计者的工具/1 拷贝控制.md new file mode 100644 index 00000000..7d0b18be --- /dev/null +++ b/C++/类设计者的工具/1 拷贝控制.md @@ -0,0 +1,71 @@ +# 拷贝控制 + +> 目录 +> * 拷贝、赋值与销毁 +> * 拷贝控制和资源管理 +> * 交换操作 +> * 拷贝控制实例 +> * 动态内存管理类 +> * 对象移动 + +> 类的特殊函数 +> * 初始化——构造函数 +> * 拷贝——拷贝构造函数 +> * 移动——移动构造函数 +> * 赋值——拷贝赋值运算符、移动赋值运算符 +> * 销毁——析构函数 + + +## 1. 拷贝构造函数 + +### 示例 +``` +class Foo{ + Foo(); + Foo(const Foo&)//拷贝构造函数 +} +``` +### 合成拷贝构造函数 + +* 编译器自动生成的拷贝构造函数。从给定的对象中依次将每个非static成员拷贝到正在创建的对象当中。 + +### 拷贝初始化 + +``` +string nies = string("efji"); +``` +* 当我门使用 赋值= 运算符时,发生拷贝初始化。 +* 将一个对象作为实参传递给一个非引用类型的形参 +* 从一个返回类型为费引用类型的函数返回一个对象 +* 用花括号列表初始化一个数组中的元素或一个聚合类中的成员 + +### 拷贝赋值运算符 + +* 编译器会自动生成合成拷贝赋值运算符 +* 需要重载赋值运算符。 + +## 2 析构函数 + +### 定义析构函数 +* 类的成员函数,由拨浪汉接类名构成,没有返回值,不接受参数。不能被重载,一个类只有一个析构函数。 + +``` +class Foo{ + public: + ~Foo(); +} +``` +### 原理 +* 在一个析构函数中,首先执行函数体,然后销毁成员。成员按初始化顺序逆序销毁。 +* 智能指针成员在西沟阶段会自动销毁。 + +### 何时调用 +* 变量离开作用域被销毁 +* 一个对象被销毁 +* 容器被销毁 +* 动态对象,使用delete + + + + + diff --git a/C++/类设计者的工具/2 操作重载与类型转换.md b/C++/类设计者的工具/2 操作重载与类型转换.md new file mode 100644 index 00000000..299bf431 --- /dev/null +++ b/C++/类设计者的工具/2 操作重载与类型转换.md @@ -0,0 +1,22 @@ +# 操作重载与类型转换 + +## 1 基本概念 + +### 基础 + +* 运算符时具有特殊名字的函数:由关键字operator和气候定义的运算符共同组成。 + +* 可以被重载的运算符 + +![](2021-03-06-23-22-55.png) + + +## 2 输入输出运算符 + +定义重载运算符。 +```C++ +ostream &operator<<(ostream &os , const Sales data &item) { + os << 工 tem . isbn() << " " << item. units sold << " " << item. revenue << " " << item.avg_price (); + return os; +} +``` \ No newline at end of file diff --git a/C++/类设计者的工具/2021-03-06-23-22-55.png b/C++/类设计者的工具/2021-03-06-23-22-55.png new file mode 100644 index 00000000..082e6a6e Binary files /dev/null and b/C++/类设计者的工具/2021-03-06-23-22-55.png differ diff --git a/C++/类设计者的工具/3 面向对象程序设计.md b/C++/类设计者的工具/3 面向对象程序设计.md new file mode 100644 index 00000000..2cca8e8b --- /dev/null +++ b/C++/类设计者的工具/3 面向对象程序设计.md @@ -0,0 +1,39 @@ +# 面向对象程序设计 + +> 面向对象的基本概念 +> * 数据抽象和封装 +> * 继承 +> * 多态(动态绑定) + + +## 1 OOP:概述 + +### 面向对象程序设计 + +* 核心思想: + * 数据抽象:类的接口与实现分离。 + * 继承:定义相似的类型,对相似的关系建模。实现代码重用。 + * 动态绑定:可以在以一定程度上忽略相似类型的区别。 + +### 继承 + +* 继承:联系在一起的类构成以中层次关系 +* 基类:层次关系的根部 +* 派生类:其他类则直接或间接地从基类继承而来。 + +* 虚函数: + +## 2 定义基类和派生类 + +## 3 虚函数 + +## 4 抽象函数 + +## 5 访问控制与继承 + + +## 6 继承中的类作用域 + +## 7 构造函数与拷贝控制 + +## 8 容器与继承 diff --git a/C++/类设计者的工具/4 模板与泛型编程.md b/C++/类设计者的工具/4 模板与泛型编程.md new file mode 100644 index 00000000..e69de29b diff --git a/C++/面试/11.初始化的方法.md b/C++/面试/11.初始化的方法.md index 3f5ac541..a5c20e61 100644 --- a/C++/面试/11.初始化的方法.md +++ b/C++/面试/11.初始化的方法.md @@ -98,25 +98,4 @@ vector b{3,4,5};//列表初始化----集合直接初始化 Car t{3,4};//列表初始化----直接初始化,构造函数。 vector ttt{Car(3.4),Car(5,6)}; ``` -* 所有其他初始化形式都是list initialization的特殊表现形式或者与其相关。理解的要点在于,list中的参数要么按构造函数的参数声明顺序,要么按aggregate类型成员声明顺序,逐个赋值。 - - - - -## 2 类的构造函数 - -### 默认构造函数 -### 合成默认构造函数 -### 委托构造函数 -### 拷贝构造函数 - - -### 构造函数类型和初始化的方法 -> 介绍初始化的方法、构造函数的类型、初始化执行的顺序。 - - -1. 列表初始化 -2. 委托构造函数 -3. 初始化函数体 -4. 值初始化。(在成员变量定义的时候给出的值) -5. 默认初始化(以上情况都没有的时候) \ No newline at end of file +* 所有其他初始化形式都是list initialization的特殊表现形式或者与其相关。理解的要点在于,list中的参数要么按构造函数的参数声明顺序,要么按aggregate类型成员声明顺序,逐个赋值。 \ No newline at end of file diff --git a/C++/面试/12.nullptr、NULL、0.md b/C++/面试/12.nullptr、NULL、0.md index 0fe4a154..a7b144df 100644 --- a/C++/面试/12.nullptr、NULL、0.md +++ b/C++/面试/12.nullptr、NULL、0.md @@ -37,4 +37,4 @@ foo_t *f = NULL; ![](2021-03-05-17-00-11.png) ### C++中的nullptr -* nullptr 关键字,被自动转换为各种pointer类型。但他不会不转换为任何证书类型。 +* nullptr 关键字,被自动转换为各种pointer类型。但他不会不转换为任何整型类型。防止null作为参数的时候出现函数重载的错误。 diff --git a/C++/面试/15.构造函数.md b/C++/面试/15.构造函数.md new file mode 100644 index 00000000..3c60151f --- /dev/null +++ b/C++/面试/15.构造函数.md @@ -0,0 +1,29 @@ + + +## 2 类的构造函数 + +与类同名的,没有返回值的函数,用来创建、管理该类。 + +### 合成构造函数 + +编译器自动生成的一系列构造函数。包括以下几种 +* 合成默认构造函数 + * 当用户定义了任意类型的构造函数,编译器不再自动生成合成默认构造函数 +* 合成拷贝构造函数 + * 即是用户定义了其他类型的构造函数,编译器还会自动生成合成拷贝构造函数。 +* 合成析构函数 + +### 默认构造函数 + +无参构造函数。 + +### 拷贝构造函数 + +唯一参数是当前类类型。 + +### 移动构造函数 + + +### 委托构造函数 + +使用已有的构造函数初始化。 diff --git a/工作日志/2021年2月27日-三月份计划.md b/工作日志/2021年2月27日-三月份计划.md index 2ef5bced..a9760afb 100644 --- a/工作日志/2021年2月27日-三月份计划.md +++ b/工作日志/2021年2月27日-三月份计划.md @@ -11,7 +11,7 @@ - 知识复习——语言(一周) - C++(primer) - 基础语法√ - - 标准库 STL + - 标准库 STL√ - 面向对象 - 设计模式(有道云笔记,gitee 设计模式库,书) - effective 系列