diff --git a/C++/标准库/12 动态内存.md b/C++/标准库/12 动态内存.md new file mode 100644 index 00000000..ee9683e8 --- /dev/null +++ b/C++/标准库/12 动态内存.md @@ -0,0 +1,136 @@ +# 动态内存 + + +## 0 C++直接管理内存 + +### 概念 + +* C++使用new分配内存,使用delete释放new分配的内存。 +* 动态对象的声明周期从创建到被释放时为止。 + + +### 使用动态内存的原因 +> 既然这么多风险为什么要使用动态内存 +1. 程序不知道自己需要使用给多少对象。动态循环创建多个对象。(容器,包括字符串string,都是使用动态内存管理自身的存储。) +2. 程序不知道所需对象的准确类型。运行过程中创建对象。 +3. 程序需要在多个对象间共享数据。多个对象共享相同的状态。 + + +### 申请内存 + +* new无法围棋分配的对象命名,而是返回一个指向该对象的指针。 +``` +int * p = new int; +``` +* 动态分配的对象执行默认初始化操作。内置类型和组合类型的对象是未定义的。类类型的对象使用默认构造函数进行初始化。 + +* 可以动态分配const对象 +``` +const int * pci = new const int(1024); +``` +* 内存耗尽后,new表达式会失败。抛出bad_alloc异常。 + +### 释放内存 +* 使用delete来释放内存。将动态内存归还给系统。 +* delete指针必须指向动态分配的内存,或一个空指针。 +* 释放一块非new分配的内存,或者将相同的指针释放多次,行为是未定义。产生错误。 +* delete对象之后,指针指向的地址被释放了,指针无效。但是指针依旧保存着原先的地址。编程**悬空指针**。 + + +## 1 动态内存与智能指针 +> 所以智能指针使用过来做动态内存管理的。普通的局部变量及其指针,不需要智能指针。智能指针是辅助new delete来管理动态内存的。智能指针就是为了解决一下问题。 + + +### 两个问题 +指针直接管理内存存在两个问题: + +1. 没有释放内存,导致内存泄露。 +2. 访问已经释放的内存,引起引用非法内存的指针。 + +### 智能指针 + +* share_ptr 允许多个指针指向同一对象 +* unique_ptr 独占所指向的对象 + +* weak_ptr伴随类。弱引用。指向shared_ptr所管理的对象。 + +### 头文件 +``` +#include +``` +### 智能指针的基础操作 +![](2021-03-06-17-05-19.png) + + +## 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); +``` + +### shared_ptr拷贝和引用计数 + +* shared_ptr 都有一个关联的计数器。引用计数。每次copy一个shared_ptr,计数器都会递增。例如将它作为参数传递给一个函数,或者作为函数的返回值。 +* 一旦一个shared_ptr的计数器变为0.它就会自动释放自己所管理的内存。使用析构函数,销毁自身。 +* 所以当它为局部变量,并且退出局部作用域后,所有的指针变量自动销毁,其所对应的动态分配的内存对象的引用计数就回变为零,此时动态内存会自动销毁。 + +![](2021-03-06-17-26-40.png) + + +### shared_ptr和new申请内存 +* shared_ptr可以使用make_shared创建对象。也可以使用new返回的指针来初始化智能指针。此时不需要delete来释放。 + +``` +share_ptr p2(new int(42)); +``` +### shared_ptr的其他方法 + +![](2021-03-06-17-43-51.png) + +## 3 动态内存管理 unique_ptr + +![](2021-03-06-17-58-42.png) +* unique_ptr是弱化的shared_ptr。某个时刻只能有一个unique_ptr直线跟一个给定的对象。当unique_ptr被销毁时,它所指向的对象也被销毁。 +* unique_ptr需要绑定到一个new返回的指针上。直接将指针置为空,指针指向的对象就会被释放。可以使用delete释放unique_ptr +* unique_ptr不支持普通的拷贝和赋值操作。但是可以考别或赋值一个将要被销毁的unique_ptr.例如return unique_ptr。实现控制权转移 +``` +unique_ptr clone(int p){ + return unique_ptr(new int(p)); +}//返回了一个动态内存的unique_ptr +``` +* 可以release放弃控制权,把控制权移交给新的智能指针。实现动态内存的控制权转移。 +``` +unique_ptr m=new int; +unique_ptr n = m.release();//m放弃所有权转移给n +``` +## 4 动态内存管理weak_ptr +* 不控制所指向对象生存期的智能指针。它指向一个由shared_ptr管理的对象。 +* 将weak_ptr绑定到shared_ptr上不会改变shared_ptr的引用计数。当shared_ptr被销毁,对象就回被释放。 + +![](2021-03-06-18-09-20.png) + +* 使用shared_ptr初始化weak_ptr + +``` +shared_ptr p = make_shared(42); +weak_ptrwp(p); +``` +* 由于weak_ptr指向的对象可能不存在,使用lock检查weak_ptr指向的对象是否存在。 + +``` +if(shared_ptrnp = wp.lock()){ + +} +``` + +## 4 动态数组 + +## 5 文本查询程序 \ No newline at end of file diff --git a/C++/标准库/12.cpp b/C++/标准库/12.cpp new file mode 100644 index 00000000..f6348c77 --- /dev/null +++ b/C++/标准库/12.cpp @@ -0,0 +1,12 @@ +#include +#include +using namespace std; + +int main(){ + //最安全的分配和使用广东台内存的方法, + shared_ptr p1 = make_shared(42); + shared_ptr p2(new int(42)); + + unique_ptr p1(new string("stego")); + return 0; +} \ No newline at end of file diff --git a/C++/标准库/13.空指针悬空指针野指针.md b/C++/标准库/13.空指针悬空指针野指针.md new file mode 100644 index 00000000..e69de29b diff --git a/C++/标准库/2 容器.md b/C++/标准库/2 容器.md index 7354c95d..a0334243 100644 --- a/C++/标准库/2 容器.md +++ b/C++/标准库/2 容器.md @@ -12,8 +12,15 @@ 4. 头尾插入元素,使用deque 5. 可以在输入阶段随机插入的时候使用list,然后将复制好的放到vector中加速访问。 +### C++ STL容器的实现 -## 2 容器的基础操作 +![](2021-03-06-15-39-37.png) + +### C++ STL容器概览 + +![](2021-03-06-15-41-19.png) + +## 2 所有容器的基础操作 ### 容器统一的操作 ![](2021-03-05-20-17-45.png) @@ -27,6 +34,7 @@ ![](2021-03-05-20-29-29.png) + ### 容器大小的操作 * size():返回容器中元素的数目 @@ -40,44 +48,7 @@ * 除了无序关联容器,都支持关系运算(> < >= <=) * 必须是相同各类型的容器,且元素类型相同才能比较。 - -## 3 顺序容器的操作 - -### 向顺序容器中添加元素 - -![](2021-03-05-20-37-12.png) - -* 在尾部添加元素push_back() -* 在头部添加元素push_front() -* 在中间添加元素insert() - - -### 在顺序容器中访问元素 - -![](2021-03-05-20-40-51.png) - -* 也可以使用迭代器访问元素。 -* at会进行安全检查抛出异常。[]不会进行检查。 - -### 在顺序容器中删除元素 - -![](2021-03-05-20-42-30.png) - -> 操作记忆 -> * back、front、push_back、push_front、pop_back、pop_front。是一组首尾相关的操作。 -> * insert、at、erase。是一组随机的操作。 - - -### foward_list的特殊操作 - -![](2021-03-05-20-54-47.png) - -### 改变容器的大小 - -![](2021-03-05-20-56-47.png) - - -## 4 容器的容量问题 +## 3 容器的容量问题 ### vector的存储 diff --git a/C++/标准库/2.1 顺序容器.md b/C++/标准库/2.1 顺序容器.md index 433ea66a..97f1ab9c 100644 --- a/C++/标准库/2.1 顺序容器.md +++ b/C++/标准库/2.1 顺序容器.md @@ -8,6 +8,40 @@ > * forward_list > * string//专门用于字符串访问的容器 +## 0 顺序容器的基础操作 + +### 向顺序容器中添加元素 + +![](2021-03-05-20-37-12.png) + +* 在尾部添加元素push_back() +* 在头部添加元素push_front() +* 在中间添加元素insert() + + +### 在顺序容器中访问元素 + +![](2021-03-05-20-40-51.png) + +* 也可以使用迭代器访问元素。 +* at会进行安全检查抛出异常。[]不会进行检查。 + +### 在顺序容器中删除元素 + +![](2021-03-05-20-42-30.png) + +> 操作记忆 +> * back、front、push_back、push_front、pop_back、pop_front。是一组首尾相关的操作。 +> * insert、at、erase。是一组随机的操作。 + + +### foward_list的特殊操作 + +![](2021-03-05-20-54-47.png) + +### 改变容器的大小 + +![](2021-03-05-20-56-47.png) ## 1 array diff --git a/C++/标准库/2.2 关联容器.md b/C++/标准库/2.2 关联容器.md index e69de29b..2599f3a8 100644 --- a/C++/标准库/2.2 关联容器.md +++ b/C++/标准库/2.2 关联容器.md @@ -0,0 +1,156 @@ +# 关联容器 + + +## 1 关联容器概述 + +### 关联容器与顺序容器的区别 + +关联容器和顺序容器有着根本不同。关联容器中的元素是按关键字来把偶才能和访问的。书序容器中的元素是按他们在容器中的位置来顺序保存和访问的。 + +### 两个基础类型 + +* map:键值对key-value。关键字是索引,值表示与索引相关的数据。 +* set:每个元素只包含一个关键字。支持高校的关键字查询操作。 + + +### 关联容器之间的区别 +* 是一个set或者map +* 要求不重复的关键字,允许重复的关键字。 +* 按顺序保存元素。无序保存。 + +![](2021-03-06-15-48-08.png) + +### 关联容器的头文件 + +* ``:map,multimap +* ``:set,multiset +* ``:unorder_map,unorder_multimap +* ``:unorder_set,unorder_multiset + +### map和set的使用 + +``` +#include +#include +#include + +using namespace std; + +int main(){ + + map word_count; + string word="hello"; + word_count[word]=10; + word_count["world"]=35; + //遍历map + for(auto &w:word_count){ + cout<<"w.first"< ss{"yin","kang","long","hello","world"}; + for (auto s : ss) + { + cout< word_count;//空容器 + set ex{"the","to"};//初始化set + map wc{ + {"jo",10}, + {"yin",13}, + {"kang",53}, + {"long",3} + };//初始化map +``` +* multimap、multiset的定义和初始化。允许关键字的重复。 + +``` + //可以使用顺序容器初始化关联容器multiset初始化 + vector vec{1,2,3,4,5,5,4,3,2,1}; + set iset(vec.begin(),vec.end()); + multiset mset(vec.begin(),vec.end()); + cout< author{'James","joyce"}; +``` + +* pair上的操作 + +![](2021-03-06-16-18-21.png) + + + +## 2 关联容器的基础操作 + +### 关联容器额外的类型名 +![](2021-03-06-16-20-49.png) + + +### 关联容器的迭代器和元素遍历 + +``` + //使用迭代器遍历关联容器 + + auto map_it = word_count.cbegin(); + while(map_it != word_count.cend()){ + cout<first<second< +#include +#include +#include +#include +#include +using namespace std; + +int main(){ + + map word_count;//空容器 + set ex{"the","to"};//初始化set + map wc{ + {"jo",10}, + {"yin",13}, + {"kang",53}, + {"long",3} + };//初始化map + string word="hello"; + word_count[word]=10; + word_count["world"]=35; + //遍历map + for(auto &w:word_count){ + cout<<"w.first"< ss{"yin","kang","long","hello","world"}; + for (auto s : ss) + { + cout< vec{1,2,3,4,5,5,4,3,2,1}; + set iset(vec.begin(),vec.end()); + multiset mset(vec.begin(),vec.end()); + cout<first<second< people; + people["yin"]=10; + people["yin"]++; + + cout< out_iter(cout,"\n"); + *out_iter =10; + *out_iter = 100; +``` + +### 反向迭代器 + +从容器的尾元素向首元素反向移动的迭代器。递增递减操作相反。 + diff --git a/C++/标准库/3.cpp b/C++/标准库/3.cpp index 2dbd04e2..73c276af 100644 --- a/C++/标准库/3.cpp +++ b/C++/标准库/3.cpp @@ -34,5 +34,8 @@ int main(){ str_it++; cout<<*str_it< out_iter(cout,"\n"); + *out_iter =10; + *out_iter = 100; return 0; } \ No newline at end of file diff --git a/C++/标准库/4 算法.md b/C++/标准库/4 算法.md index 1c404a4e..e9716285 100644 --- a/C++/标准库/4 算法.md +++ b/C++/标准库/4 算法.md @@ -1,7 +1,7 @@ # 算法 -## 1 算法概览 +## 1 泛型算法概览 ### 头文件 #include//标准库算法 @@ -18,7 +18,7 @@ * 只读算法。不改变元素的值 * 更易算法。该表容器的元素 -### 示例 +### 常用算法示例 * 只读算法 accumulate() @@ -45,5 +45,66 @@ find() find_if() -## 2 +## 2 泛型算法的结构 + +### 五类迭代器 +泛型算法只要能够提供五个迭代器类别,所有到的泛型算法都能够执行。每个算法都会对他的每个迭代器指明提供哪类迭代器。 + +![](2021-03-06-15-13-07.png) + +### 输入迭代器 + +* 可以读取序列中的元素 + * 比较两个迭代器的运算符==,!= + * 推进迭代器前置或后置的递增运算符++ + * 用于读取元素的解引用运算符* -> + +### 输出迭代器 +* 可以向序列中写入元素 + * 用于推进迭代器前置和后置的递增运算 + * 用于写入的解引用运算符。只能是左值。 + +### 前向迭代器 +* 只能沿一个方向运动 + +### 双向迭代器 +* 可以正反两个方向运动。支持++和-- + +### 随机访问迭代器 + +* 常量时间内随机访问序列中任意元素的能力。下标访问。 + * 用于比较迭代器相对位置的关系运算符< > <= >=,基于随机访问能力。 + * 迭代器和一个整数值的加减运算 + += - -= + * 用于计算迭代器距离的运算符-。基于随机访问能力 + * 下标运算符[]。提供随机访问能力 + + +### 算法的形参模式 + +* 必然是一下四中形式之一 + * 接受单个目标迭代器的算法 + * 接受第二个输入序列的算法 + +![](2021-03-06-15-23-17.png) + +### 算法的命名规范 +* 算法有多个重载版本 +* _if结尾多加一个**谓词**。可以传递一个函数。 +* _copy结尾,表示多加一个序列用来拷贝结果。 + + +## 3 特定容器算法 + +### list和forward_list的特定算法 + +* 成员函数中的算法 + + +![](2021-03-06-15-27-21.png) + +* splice算法 + +![](2021-03-06-15-28-46.png) + + diff --git a/C++/标准库/5.cpp b/C++/标准库/5.cpp new file mode 100644 index 00000000..e69de29b diff --git a/C++/标准库/6.cpp b/C++/标准库/6.cpp new file mode 100644 index 00000000..e69de29b diff --git a/C++/面试/13.动态内存管理实现.md b/C++/面试/13.动态内存管理实现.md new file mode 100644 index 00000000..285de0e8 --- /dev/null +++ b/C++/面试/13.动态内存管理实现.md @@ -0,0 +1,9 @@ +# 动态内存 + +## 1 C中动态内存的实现 + + +## 2 C++中动态内存的实现 + + +## 3 两者的区别和优势劣势 \ No newline at end of file diff --git a/工作日志/2021年2月27日-三月份计划.md b/工作日志/2021年2月27日-三月份计划.md index ec6d8ade..2ef5bced 100644 --- a/工作日志/2021年2月27日-三月份计划.md +++ b/工作日志/2021年2月27日-三月份计划.md @@ -8,7 +8,7 @@ ### 工作 - 制作简历(明天) -- 知识复习——语言 +- 知识复习——语言(一周) - C++(primer) - 基础语法√ - 标准库 STL @@ -18,10 +18,10 @@ - 系列视频 - 问题专项解决) - Java(语法、标准库) -- 知识复习——算法 +- 知识复习——算法(一周) - 数据结构 - 算法 -- 知识复习——基础 +- 知识复习——基础(一周) - 计算机网络 - 数据库 - 操作系统