├── 00.编译链接加载内存专题 ├── README.md └── img │ └── elf.png ├── 01.C++基础部分 ├── README.md ├── img │ ├── RTTI.png │ ├── complex.png │ ├── complex2.png │ ├── ctor_init_list.png │ ├── delete.png │ ├── delete2.png │ ├── extends.png │ ├── fraction.png │ ├── malloc.png │ ├── malloc2.png │ ├── new.png │ ├── placement_new.png │ ├── smart_prt.png │ ├── static.png │ ├── static_template.png │ ├── static_template2.png │ ├── template.png │ ├── vptr.png │ └── vtpr2.png └── src │ ├── 00.const_member_func.cpp │ ├── 01.friends.cpp │ ├── 02.explicit.cpp │ ├── 03.struct.cpp │ ├── 04.union.cpp │ ├── 05.enum.cpp │ ├── 06.sieze_union.cpp │ ├── 07.sizeof_struct.cpp │ ├── 076.nocopyable.cpp │ ├── 08.sizeof_empty_class.cpp │ ├── 09.sizeof_not_empty_class.cpp │ ├── 10.sizeof_not_empty_class2.cpp │ ├── 100.register.c │ ├── 101.const.c │ ├── 102.static.cpp │ ├── 102.static2.cpp │ ├── 103.bind1st2nd.cpp │ ├── 109.memory_allocate.cpp │ ├── 11.sizeof_only_func_class.cpp │ ├── 110.=delete.cpp │ ├── 111.=delete2.cpp │ ├── 112.=delete3.cpp │ ├── 113.=delete4.cpp │ ├── 116.vptr.cpp │ ├── 116.vptr2.cpp │ ├── 12.sizeof_dtor_ctor_func_class.cpp │ ├── 120.virtual_extens.cpp │ ├── 121.vector_resize_reverse.cpp │ ├── 123.vector_swap.cpp │ ├── 128.moveCopy.cpp │ ├── 129.mutable.cpp │ ├── 13.sizeof_of_vdtor_class.cpp │ ├── 14.sizeof_extends_class.cpp │ ├── 15.virtual_function.cpp │ ├── 16.virtual_dtor.cpp │ ├── 17.function_template.cpp │ ├── 18.static_cast.cpp │ ├── 19.dynamic_cast.cpp │ ├── 20.const_cast.cpp │ ├── 21.reinterpret_cast.cpp │ └── 99.sturct2.cpp ├── 02.C++11 ├── README.md ├── lambda表达式 │ ├── README.md │ └── src │ │ ├── 22.lambda.cpp │ │ └── 23.lambda2.cpp ├── 函数绑定 │ ├── README.md │ └── src │ │ └── 24.bind_function.cpp ├── 可变参数 │ ├── README.md │ └── img │ │ └── args.png ├── 右值与完美转发 │ ├── README.md │ └── img │ │ └── &&.png ├── 并发编程 │ ├── 01.多线程编程 │ │ ├── README.md │ │ └── src │ │ │ ├── 33.thread_create.cpp │ │ │ ├── 34.detech_thread.cpp │ │ │ ├── 35.thread_joinable.cpp │ │ │ ├── 36.thread_functors.cpp │ │ │ ├── 37.thread_lambda.cpp │ │ │ ├── 38.thread_pass_paras.cpp │ │ │ ├── 39.thread_pass_ref.cpp │ │ │ ├── 40.thread_move_paras.cpp │ │ │ ├── 41.thread_copy_move.cpp │ │ │ ├── 42.thread_ID.cpp │ │ │ ├── 43.how_many_threads_in_cpu.cpp │ │ │ ├── 44.threads_with_lambda.cpp │ │ │ └── 45.threads_with_lambda2.cpp │ ├── 02.线程同步 │ │ ├── README.md │ │ └── src │ │ │ ├── 46.thread_mutex.cpp │ │ │ ├── 47.thread_lock_guard.cpp │ │ │ ├── 48.thread_safe_stack_demo.cpp │ │ │ ├── 49.thread_cond_var.cpp │ │ │ ├── 50.thread_cond_wait.cpp │ │ │ ├── 51.thread_cond_waitfor.cpp │ │ │ ├── 52.thread_cond_notify_one.cpp │ │ │ └── 53.thread_cond_notify_all.cpp │ ├── 03.future │ │ ├── README.md │ │ └── src │ │ │ ├── 55.thread_promise.cpp │ │ │ ├── 56.thread_promise_ctor.cpp │ │ │ ├── 57.thread_promise_exception.cpp │ │ │ ├── 58.thread_packaged_task.cpp │ │ │ ├── 59.thread_packaged_task_ctor.cpp │ │ │ ├── 60.thread_packaged_task_valid.cpp │ │ │ ├── 61.thread_packaged_task_reset.cpp │ │ │ ├── 62.thread_future.cpp │ │ │ ├── 63.thread_future_shared.cpp │ │ │ ├── 64.thread_future_get.cpp │ │ │ ├── 65.thread_future_valid.cpp │ │ │ ├── 66.thread_future_wait.cpp │ │ │ ├── 67.thread_future_wait_for.cpp │ │ │ ├── 68.thread_future_async.cpp │ │ │ └── 69.thread_future_launch.cpp │ └── 04.线程池 │ │ ├── README.md │ │ └── src │ │ ├── 54.thread_pool_demo.cpp │ │ ├── 70.result_of.cpp │ │ ├── 71.func_package.cpp │ │ ├── ThreadPool.h │ │ └── mythread │ │ ├── MyThreadPool.cpp │ │ ├── MyThreadPool.h │ │ └── testMyThredPool.cpp └── 智能指针 │ ├── README.md │ ├── img │ └── circle_reference.png │ └── src │ ├── 25.shared_ptr.cpp │ ├── 26.shared_ptr2.cpp │ ├── 27.unique_ptr.cpp │ ├── 28.weak_ptr.cpp │ ├── 29.circle_reference.cpp │ ├── 30.circle_reference2.cpp │ ├── 31.circle_reference_solve.cpp │ └── 32.realize_smart_ptr.cpp ├── 03.STL ├── 01.STL使用 │ ├── algorithm │ │ ├── README.md │ │ ├── img │ │ │ └── algorithm.png │ │ └── src │ │ │ ├── 87.stl_algorithm_one_func_obj.cpp │ │ │ ├── 88.stl_algorithm_one_pred.cpp │ │ │ ├── 89.stl_algorithm_two_func_obj.cpp │ │ │ ├── 90.stl_algorithm_two_pred.cpp │ │ │ ├── 91.stl_algorithm_std_func_obj.cpp │ │ │ ├── 92.stl_algorithm_std_relation_func_obj.cpp │ │ │ ├── 93.stl_algorithm_bind1st_2nd.cpp │ │ │ ├── 94.stl_algorithm_for_each.cpp │ │ │ └── 95.stl_algorithm_transform.cpp │ ├── deque │ │ ├── README.md │ │ └── src │ │ │ └── 75.stl_deque.cpp │ ├── heap │ │ ├── README.md │ │ ├── img │ │ │ └── heap.png │ │ └── src │ │ │ └── 98.stl_heap.cpp │ ├── list │ │ ├── README.md │ │ └── src │ │ │ └── 79.stl_list.cpp │ ├── map │ │ ├── README.md │ │ └── src │ │ │ ├── 84.stl_map1.cpp │ │ │ ├── 85.stl_map2.cpp │ │ │ └── 86.stl_multimap.cpp │ ├── priority_queue │ │ ├── README.md │ │ └── src │ │ │ └── 80.stl_priority_queue.cpp │ ├── queue │ │ ├── README.md │ │ └── src │ │ │ └── 77.stl_queue.cpp │ ├── set │ │ ├── README.md │ │ └── src │ │ │ ├── 81.stl_set_functor.cpp │ │ │ ├── 82.stl_set_find.cpp │ │ │ └── 83.stl_set.cpp │ ├── stack │ │ ├── README.md │ │ └── src │ │ │ └── 76.stl_stack.cpp │ ├── string │ │ ├── README.md │ │ └── src │ │ │ ├── 72.stl_string.cpp │ │ │ └── 78.stl_string2.cpp │ └── vector │ │ ├── README.md │ │ ├── img │ │ └── iterator.png │ │ └── src │ │ ├── 73.stl_vector1.cpp │ │ └── 74.stl_vector2.cpp └── 02.STL原理 │ ├── README.md │ ├── img │ ├── accumulate.png │ ├── adapter.png │ ├── adaptor.png │ ├── algo.png │ ├── algo10.png │ ├── algo11.png │ ├── algo12.png │ ├── algo2.png │ ├── algo3.png │ ├── algo4.png │ ├── algo5.png │ ├── algo6.png │ ├── algo7.png │ ├── algo8.png │ ├── algo9.png │ ├── allocator.png │ ├── allocator10.png │ ├── allocator2.png │ ├── allocator3.png │ ├── allocator4.png │ ├── allocator5.png │ ├── allocator6.png │ ├── allocator7.png │ ├── allocator8.png │ ├── allocator9.png │ ├── alog9.png │ ├── array.png │ ├── array2.png │ ├── array3.png │ ├── binary_search.png │ ├── bind2nd.png │ ├── count.png │ ├── deque.png │ ├── deque10.png │ ├── deque11.png │ ├── deque2.png │ ├── deque3.png │ ├── deque4.png │ ├── deque5.png │ ├── deque6.png │ ├── deque7.png │ ├── deque8.png │ ├── deque9.png │ ├── find.png │ ├── fl.png │ ├── for_each.png │ ├── forward_list.png │ ├── func1.png │ ├── func2.png │ ├── func3.png │ ├── func4.png │ ├── iterator1.png │ ├── iterator10.png │ ├── iterator11.png │ ├── iterator12.png │ ├── iterator2.png │ ├── iterator3.png │ ├── iterator4.png │ ├── iterator5.png │ ├── iterator6.png │ ├── iterator7.png │ ├── iterator8.png │ ├── iterator9.png │ ├── list.png │ ├── map.png │ ├── multimap.png │ ├── multiset.png │ ├── new.png │ ├── not1.png │ ├── queue.png │ ├── queue2.png │ ├── replace.png │ ├── set.png │ ├── sort.png │ ├── sort2.png │ ├── sq.png │ ├── sq2.png │ ├── sq3.png │ ├── stack.png │ ├── stack2.png │ ├── stl1.png │ ├── stl2.png │ ├── stl3.png │ ├── traits.png │ ├── traits2.png │ ├── traits3.png │ ├── traits4.png │ ├── traits5.png │ ├── traits6.png │ ├── unordered_multimap.png │ ├── unordered_multiset.png │ ├── vector.png │ ├── vector2.png │ ├── vector3.png │ ├── vector4.png │ └── vector5.png │ ├── reference │ └── stl.pdf │ └── src │ ├── 01.test_array.cpp │ ├── 02.test_vector.cpp │ ├── 03.test_list.cpp │ ├── 04.test_forward_list.cpp │ ├── 05.test_deque.cpp │ ├── 06.test_queue.cpp │ ├── 07.test_stack.cpp │ ├── 08.test_multiset.cpp │ ├── 09.test_multimap.cpp │ ├── 10.test_unordered_multiset.cpp │ ├── 11.test_unordered_multimap.cpp │ ├── 12.test_set.cpp │ ├── 13.test_map.cpp │ ├── 14.test_unordered_set.cpp │ ├── 15.test_unordered_map.cpp │ ├── 16.test_accumulate.cpp │ ├── 17.test_for_each.cpp │ ├── 18.test_sort.cpp │ ├── 96.Traits_problem.cpp │ ├── 97.Traits_solve.cpp │ └── sample.cpp └── 04.内存管理 ├── 内存管理.pdf └── 内存管理第五讲.pdf /00.编译链接加载内存专题/README.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | - [底层知识](#%E5%BA%95%E5%B1%82%E7%9F%A5%E8%AF%86) 6 | - [程序虚拟地址空间、栈、堆](#%E7%A8%8B%E5%BA%8F%E8%99%9A%E6%8B%9F%E5%9C%B0%E5%9D%80%E7%A9%BA%E9%97%B4%E6%A0%88%E5%A0%86) 7 | - [段错误](#%E6%AE%B5%E9%94%99%E8%AF%AF) 8 | - [编译链接](#%E7%BC%96%E8%AF%91%E9%93%BE%E6%8E%A5) 9 | - [1、编译链接过程](#1%E7%BC%96%E8%AF%91%E9%93%BE%E6%8E%A5%E8%BF%87%E7%A8%8B) 10 | - [2、目标文件](#2%E7%9B%AE%E6%A0%87%E6%96%87%E4%BB%B6) 11 | - [3、链接的接口—符号](#3%E9%93%BE%E6%8E%A5%E7%9A%84%E6%8E%A5%E5%8F%A3%E7%AC%A6%E5%8F%B7) 12 | - [Linux 的共享库(Shared Library)](#linux-%E7%9A%84%E5%85%B1%E4%BA%AB%E5%BA%93shared-library) 13 | - [ELF 文件格式](#elf-%E6%96%87%E4%BB%B6%E6%A0%BC%E5%BC%8F) 14 | - [.bss段的意义](#bss%E6%AE%B5%E7%9A%84%E6%84%8F%E4%B9%89) 15 | - [内存泄漏与内存溢出](#%E5%86%85%E5%AD%98%E6%B3%84%E6%BC%8F%E4%B8%8E%E5%86%85%E5%AD%98%E6%BA%A2%E5%87%BA) 16 | - [1、概念和区别](#1%E6%A6%82%E5%BF%B5%E5%92%8C%E5%8C%BA%E5%88%AB) 17 | - [2、内存泄漏的分类](#2%E5%86%85%E5%AD%98%E6%B3%84%E6%BC%8F%E7%9A%84%E5%88%86%E7%B1%BB) 18 | - [检测内存泄漏](#%E6%A3%80%E6%B5%8B%E5%86%85%E5%AD%98%E6%B3%84%E6%BC%8F) 19 | - [(1)检查内存泄漏](#1%E6%A3%80%E6%9F%A5%E5%86%85%E5%AD%98%E6%B3%84%E6%BC%8F) 20 | - [(2)检查使用未初始化内存](#2%E6%A3%80%E6%9F%A5%E4%BD%BF%E7%94%A8%E6%9C%AA%E5%88%9D%E5%A7%8B%E5%8C%96%E5%86%85%E5%AD%98) 21 | - [(3)其他](#3%E5%85%B6%E4%BB%96) 22 | 23 | 24 | 25 | ## 底层知识 26 | 27 | 参考 28 | > https://github.com/hujiese/interview#%EF%B8%8F-%E9%93%BE%E6%8E%A5%E8%A3%85%E8%BD%BD%E5%BA%93 29 | 30 | > https://www.nowcoder.com/tutorial/93/8f140fa03c084299a77459dc4be31c95 31 | 32 | ### 程序虚拟地址空间、栈、堆 33 | 34 | 程序的虚拟地址空间分布如下 35 | 36 | ![](https://camo.githubusercontent.com/1195e558ce80fc9016b570cbb797778b80faef0e/68747470733a2f2f692e696d6775722e636f6d2f766757375a716d2e706e67) 37 | 38 | 32bitCPU可寻址4G线性空间,每个进程都有各自独立的4G逻辑地址,其中0~3G是用户态空间,3~4G是内核空间(3G用户空间和1G内核空间)不同进程相同的逻辑地址会映射到不同的物理地址中。其逻辑地址其划分如下: 39 | 40 | * 静态区域 41 | 42 | text segment(代码段):包括只读存储区和文本区,其中只读存储区存储字符串常量,文本区存储程序的机器代码。 43 | 44 | data segment(数据段):存储程序中已初始化的全局变量和静态变量。 45 | 46 | bss segment:存储未初始化的全局变量和静态变量(局部+全局),以及所有被初始化为0的全局变量和静态变量,对于未初始化的全局变量和静态变量,程序运行main之前时会统一清零。即未初始化的全局变量编译器会初始化为0。 47 | 48 | * 动态区域: 49 | 50 | heap(堆):一般由程序员分配释放,若程序员不释放,程序结束时可能由操作系统回收,用来容纳应用程序动态分配的内存区域。当进程未调用malloc时是没有堆段的,只有调用malloc时采用分配一个堆,并且在程序运行过程中可以动态增加堆大小(移动break指针),从低地址向高地址增长。分配小内存时使用该区域。堆的起始地址由mm_struct 结构体中的start_brk标识,结束地址由brk标识。堆分配算法有:空闲链表(Free List)、位图(Bitmap)和对象池。 51 | 52 | memory mapping segment(映射区):存储动态链接库等文件映射、申请大内存(malloc时调用mmap函数) 53 | 54 | stack(栈):栈保存了一个函数调用所需要的维护信息,常被称为堆栈帧(Stack Frame)或活动记录(Activate Record),使用栈空间存储函数的返回地址、参数、局部变量、临时变量(包括函数的非静态局部变量以及编译器自动生成的其他临时变量)、返回值、保存上下文(包括函数调用前后需要保持不变的寄存器)。栈从高地址向低地址增长。在创建进程时会有一个最大栈大小,Linux可以通过ulimit命令指定。 55 | 56 | ### 段错误 57 | 58 | 典型的非法指针解引用造成的错误。当指针指向一个不允许读写的内存地址,而程序却试图利用指针来读或写该地址时,会出现这个错误。 59 | 60 | 普遍原因: 61 | 62 | * 试图修改字符串常量的内容 63 | * 将指针初始化为 NULL,之后没有给它一个合理的值就开始使用指针 64 | * 没用初始化栈中的指针,指针的值一般会是随机数,之后就直接开始使用指针(野指针,虽然释放了动态分配的内存,但指针的内容却没有置为nullptr,指向一个不存在的空间) 65 | 66 | ### 编译链接 67 | 68 | #### 1、编译链接过程 69 | 70 | 各平台文件格式: 71 | 72 | 平台| 可执行文件| 目标文件| 动态库/共享对象| 静态库 73 | ---|---|---|---|--- 74 | Windows|exe| obj| dll |lib 75 | Unix/Linux| ELF、out| o| so| a 76 | 77 | 编译链接过程: 78 | 79 | * 1、预编译(预编译器处理如 #include、#define 等预编译指令,生成 .i 或 .ii 文件) 80 | * 2、编译(编译器进行词法分析、语法分析、语义分析、中间代码生成、目标代码生成、优化,生成 .s 文件) 81 | * 3、汇编(汇编器把汇编码翻译成机器码,生成 .o 文件) 82 | * 4、链接(连接器进行地址和空间分配、符号决议、重定位,生成 .out 文件) 83 | 84 | 现在版本 GCC 把预编译和编译合成一步,预编译编译程序 cc1、汇编器 as、连接器 ld。MSVC 编译环境,编译器 cl、连接器 link、可执行文件查看器 dumpbin。 85 | 86 | #### 2、目标文件 87 | 88 | 编译器编译源代码后生成的文件叫做目标文件。目标文件从结构上讲,它是已经编译后的可执行文件格式,只是还没有经过链接的过程,其中可能有些符号或有些地址还没有被调整。 89 | 90 | 可执行文件(Windows 的 .exe 和 Linux 的 ELF)、动态链接库(Windows 的 .dll 和 Linux 的 .so)、静态链接库(Windows 的 .lib 和 Linux 的 .a)都是按照可执行文件格式存储(Windows 按照 PE-COFF,Linux 按照 ELF)。 91 | 92 | 目标文件存储结构: 93 | 94 | 段| 功能 95 | ---|--- 96 | File Header| 文件头,描述整个文件的文件属性(包括文件是否可执行、是静态链接或动态连接及入口地址、目标硬件、目标操作系统等) 97 | .text section| 代码段,执行语句编译成的机器代码 98 | .data section| 数据段,已初始化的全局变量和局部静态变量 99 | .bss section| BSS 段(Block Started by Symbol),未初始化的全局变量和局部静态变量(因为默认值为 0,所以只是在此预留位置,不占空间) 100 | .rodata section| 只读数据段,存放只读数据,一般是程序里面的只读变量(如 const 修饰的变量)和字符串常量 101 | .comment section| 注释信息段,存放编译器版本信息 102 | .note.GNU-stack section| 堆栈提示段 103 | 104 | #### 3、链接的接口—符号 105 | 106 | 在链接中,目标文件之间相互拼合实际上是目标文件之间对地址的引用,即对函数和变量的地址的引用。我们将函数和变量统称为符号(Symbol),函数名或变量名就是符号名(Symbol Name)。 107 | 108 | 如下符号表(Symbol Table): 109 | 110 | Symbol(符号名)| Symbol Value (地址) 111 | ---|--- 112 | main| 0x100 113 | Add| 0x123 114 | ...| ... 115 | 116 | ### Linux 的共享库(Shared Library) 117 | 118 | Linux 下的共享库就是普通的 ELF 共享对象。 119 | 120 | 共享库版本更新应该保证二进制接口 ABI(Application Binary Interface)的兼容 121 | 122 | * 命名 123 | 124 | 例如:libname.so.x.y.z 125 | * x:主版本号,不同主版本号的库之间不兼容,需要重新编译 126 | * y:次版本号,高版本号向后兼容低版本号 127 | * z:发布版本号,不对接口进行更改,完全兼容 128 | 129 | * 路径 130 | 131 | 大部分包括 Linux 在内的开源系统遵循 FHS(File Hierarchy Standard)的标准,这标准规定了系统文件如何存放,包括各个目录结构、组织和作用。 132 | 133 | * /lib:存放系统最关键和最基础的共享库,如动态链接器、C 语言运行库、数学库等 134 | * /usr/lib:存放非系统运行时所需要的关键性的库,主要是开发库 135 | * /usr/local/lib:存放跟操作系统本身并不十分相关的库,主要是一些第三方应用程序的库 136 | 137 | 动态链接器会在 /lib、/usr/lib 和由 /etc/ld.so.conf 配置文件指定的,目录中查找共享库 138 | 139 | * 环境变量 140 | 141 | * LD_LIBRARY_PATH:临时改变某个应用程序的共享库查找路径,而不会影响其他应用程序 142 | * LD_PRELOAD:指定预先装载的一些共享库甚至是目标文件 143 | * LD_DEBUG:打开动态链接器的调试功能 144 | 145 | ### ELF 文件格式 146 | 147 | 参考 [ELF文件格式](./img/elf.png) 148 | 149 | > https://www.cnblogs.com/gatsby123/p/9750187.html 150 | 151 | ### .bss段的意义 152 | 153 | **.bss不占据实际的磁盘空间,只在段表中记录大小,在符号表中记录符号。当文件加载运行时,才分配空间以及初始化。** 154 | 155 | 早期的计算机存储设备是很贵的,而很多时候,数据段里的全局变量都是0(或者没有初始值),那么存储这么多的0到目标文件里其实是没有必要的。所以为了节约空间,在生成目标文件的时候,就把没有初始值(实际就是0)的数据段里的变量都放到BSS段里,这样目标文件就不需要那么大的体积里(节约磁盘空间)。**只有当目标文件被载入的时候,加载器负责把BSS段清零(一个循环就可以搞定)**。 之后,这个规则慢慢的成为一个标准配置,大多数编译器也就都支持了BSS段。 156 | 157 | .data节中定义的数据项与.bss节中定义的数据项之间存在至关重要的区别:**.data节中的数据项增加了可执行文件的大小。.bss部分中的数据项没有**。可以在.bss中定义一个占用16,000字节(或更多,有时更多的字节)的缓冲区,并且几乎不增加任何内容(描述中大约50字节)。 158 | 159 | **总之,.bss段目的是为了节省空间,因为如果所有的未初始化全局变量都放在.data段里,.data段必定很大,占用空间,这是没有必要的浪费,只需要在加载运行程序时来初始化这些变量即可。** 160 | 161 | ## 内存泄漏与内存溢出 162 | 163 | #### 1、概念和区别 164 | 165 | 内存泄露(memory leak)是指程序在申请内存后,无法释放已申请的内存空间就造成了内存泄漏,一次内存泄漏似乎不会有大的影响,但内存泄漏堆积后的后果就是内存溢出。内存泄漏并非指内存在物理上的消失,而是应用程序分配某段内存后,由于设计错误,失去了对该段内存的控制,因而造成了内存的浪费。 166 | 167 | 内存溢出(out of memory)指程序申请内存时,没有足够的内存供申请者使用,或者说,给了你一块存储int类型数据的存储空间,但是你却存储long类型的数据,那么结果就是内存不够用,此时就会报错OOM,即所谓的内存溢出,简单来说就是自己所需要使用的空间比我们拥有的内存大内存不够使用所造成的内存溢出。 168 | 169 | #### 2、内存泄漏的分类 170 | 171 | * 堆内存泄漏 (Heap leak) 172 | 173 | 对内存指的是程序运行中根据需要分配通过malloc,realloc new等从堆中分配的一块内存,再是完成后必须通过调用对应的 free或者delete 删掉。如果程序的设计的错误导致这部分内存没有被释放,那么此后这块内存将不会被使用,就会产生Heap Leak。 174 | 175 | * 系统资源泄露(Resource Leak) 176 | 177 | 主要指程序使用系统分配的资源比如 Bitmap,handle ,SOCKET等没有使用相应的函数释放掉,导致系统资源的浪费,严重可导致系统效能降低,系统运行不稳定。 178 | 179 | * 没有将基类的析构函数定义为虚函数。 180 | 181 | 当基类指针指向子类对象时,如果基类的析构函数不是virtual,那么子类的析构函数将不会被调用,子类的资源没有正确是释放,因此造成内存泄露。 182 | 183 | #### 检测内存泄漏 184 | 185 | ##### (1)检查内存泄漏 186 | 187 | 可以使用linux环境下的内存泄漏检查工具Valgrind。这个工具可以使用apt-get安装。 188 | 189 | 下面这个代码: 190 | 191 | ```cpp 192 | #include 193 | #include 194 | using namespace std; 195 | void func(){ 196 | int *x=(int *)malloc( 10 * sizeof ( int ) ) ; 197 | x[10]=0; 198 | } 199 | int main(){ 200 | func(); 201 | cout<<"done"< 256 | using namespace std; 257 | int main(){ 258 | int a[5]; 259 | int i,s=0; 260 | a[0]=a[1]=a[3]=a[4]=0; 261 | for(i=0;i<5;i++) 262 | s=s+a[i]; 263 | if(s==33) 264 | cout<<"sum is 33"< 2 | using namespace std; 3 | 4 | class complex 5 | { 6 | public: 7 | complex(double r = 0, double i = 0) 8 | : re(r), im(i) 9 | { } 10 | complex& operator += (const complex&); 11 | double real() const { return re; } 12 | double imag() const { return im; } 13 | private: 14 | double re, im; 15 | }; 16 | 17 | int main(void) 18 | { 19 | complex c1(2, 1); 20 | cout << c1.real() << endl; 21 | cout << c1.imag() << endl; 22 | return 0; 23 | } -------------------------------------------------------------------------------- /01.C++基础部分/src/01.friends.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | class complex 5 | { 6 | public: 7 | complex(double r = 0, double i = 0) 8 | : re(r), im(i) 9 | { } 10 | int func(const complex& param) 11 | { 12 | return param.re + param.im; 13 | } 14 | private: 15 | double re, im; 16 | }; 17 | 18 | int main(void) 19 | { 20 | complex c1(2, 1); 21 | complex c2; 22 | cout << c2.func(c1) << endl; 23 | return 0; 24 | } -------------------------------------------------------------------------------- /01.C++基础部分/src/02.explicit.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hujiese/cpp-study/c94ec4adf61a059e7e768cabc2bcb7b276327bd6/01.C++基础部分/src/02.explicit.cpp -------------------------------------------------------------------------------- /01.C++基础部分/src/03.struct.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hujiese/cpp-study/c94ec4adf61a059e7e768cabc2bcb7b276327bd6/01.C++基础部分/src/03.struct.cpp -------------------------------------------------------------------------------- /01.C++基础部分/src/04.union.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hujiese/cpp-study/c94ec4adf61a059e7e768cabc2bcb7b276327bd6/01.C++基础部分/src/04.union.cpp -------------------------------------------------------------------------------- /01.C++基础部分/src/05.enum.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hujiese/cpp-study/c94ec4adf61a059e7e768cabc2bcb7b276327bd6/01.C++基础部分/src/05.enum.cpp -------------------------------------------------------------------------------- /01.C++基础部分/src/06.sieze_union.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | union A{ 4 | int a[5]; 5 | char b; 6 | double c; 7 | }; 8 | int main(){ 9 | cout << sizeof(A) << endl; 10 | return 0; 11 | } 12 | -------------------------------------------------------------------------------- /01.C++基础部分/src/07.sizeof_struct.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | struct B{ 4 | char a; 5 | double b; 6 | int c; 7 | }test_struct_b; 8 | int main(){ 9 | cout << sizeof(test_struct_b) << endl; 10 | return 0; 11 | } 12 | -------------------------------------------------------------------------------- /01.C++基础部分/src/076.nocopyable.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hujiese/cpp-study/c94ec4adf61a059e7e768cabc2bcb7b276327bd6/01.C++基础部分/src/076.nocopyable.cpp -------------------------------------------------------------------------------- /01.C++基础部分/src/08.sizeof_empty_class.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | class CBox{ 4 | }; 5 | int main(){ 6 | CBox boxobj; 7 | cout << sizeof(boxobj) << endl;//1 8 | } 9 | -------------------------------------------------------------------------------- /01.C++基础部分/src/09.sizeof_not_empty_class.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | class CBox{ 4 | int length, width, height; 5 | }; 6 | int main(){ 7 | CBox boxobj; 8 | cout << sizeof(boxobj) << endl; 9 | return 0; 10 | } 11 | -------------------------------------------------------------------------------- /01.C++基础部分/src/10.sizeof_not_empty_class2.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | class CBox{ 4 | int length, width, height; 5 | static int count; 6 | }; 7 | int main(){ 8 | CBox boxobj; 9 | cout << sizeof(boxobj) << endl; 10 | return 0; 11 | } 12 | -------------------------------------------------------------------------------- /01.C++基础部分/src/100.register.c: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hujiese/cpp-study/c94ec4adf61a059e7e768cabc2bcb7b276327bd6/01.C++基础部分/src/100.register.c -------------------------------------------------------------------------------- /01.C++基础部分/src/101.const.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main() 4 | { 5 | const int a = 10; 6 | int *p = (int*)&a; 7 | printf("a===>%d\n", a); 8 | *p = 11; 9 | printf("a===>%d\n", a); 10 | return 0; 11 | } 12 | -------------------------------------------------------------------------------- /01.C++基础部分/src/102.static.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hujiese/cpp-study/c94ec4adf61a059e7e768cabc2bcb7b276327bd6/01.C++基础部分/src/102.static.cpp -------------------------------------------------------------------------------- /01.C++基础部分/src/102.static2.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | void change() 5 | { 6 | static int a = 0; 7 | ++a; 8 | cout << a << endl; 9 | } 10 | 11 | int main(void) 12 | { 13 | change(); // 1 14 | change(); // 2 15 | change(); // 3 16 | change(); // 4 17 | return 0; 18 | } -------------------------------------------------------------------------------- /01.C++基础部分/src/103.bind1st2nd.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hujiese/cpp-study/c94ec4adf61a059e7e768cabc2bcb7b276327bd6/01.C++基础部分/src/103.bind1st2nd.cpp -------------------------------------------------------------------------------- /01.C++基础部分/src/109.memory_allocate.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hujiese/cpp-study/c94ec4adf61a059e7e768cabc2bcb7b276327bd6/01.C++基础部分/src/109.memory_allocate.cpp -------------------------------------------------------------------------------- /01.C++基础部分/src/11.sizeof_only_func_class.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | class CBox{ 4 | int foo(); 5 | }; 6 | int main(){ 7 | CBox boxobj; 8 | cout << sizeof(boxobj) << endl; 9 | return 0; 10 | } 11 | -------------------------------------------------------------------------------- /01.C++基础部分/src/110.=delete.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hujiese/cpp-study/c94ec4adf61a059e7e768cabc2bcb7b276327bd6/01.C++基础部分/src/110.=delete.cpp -------------------------------------------------------------------------------- /01.C++基础部分/src/111.=delete2.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hujiese/cpp-study/c94ec4adf61a059e7e768cabc2bcb7b276327bd6/01.C++基础部分/src/111.=delete2.cpp -------------------------------------------------------------------------------- /01.C++基础部分/src/112.=delete3.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hujiese/cpp-study/c94ec4adf61a059e7e768cabc2bcb7b276327bd6/01.C++基础部分/src/112.=delete3.cpp -------------------------------------------------------------------------------- /01.C++基础部分/src/113.=delete4.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hujiese/cpp-study/c94ec4adf61a059e7e768cabc2bcb7b276327bd6/01.C++基础部分/src/113.=delete4.cpp -------------------------------------------------------------------------------- /01.C++基础部分/src/116.vptr.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | class Base 5 | { 6 | public: 7 | virtual void fun1() 8 | { 9 | cout << "Base func1...." << endl; 10 | } 11 | virtual void fun2() 12 | { 13 | cout << "Base func2...." << endl; 14 | } 15 | void func3() 16 | { 17 | cout << "Base func3...." << endl; 18 | } 19 | }; 20 | 21 | class Son : public Base 22 | { 23 | public: 24 | virtual void fun1() 25 | { 26 | cout << "Son func1...." << endl; 27 | } 28 | virtual void fun2() 29 | { 30 | cout << "Son func2...." << endl; 31 | } 32 | void func3() 33 | { 34 | cout << "Son func3...." << endl; 35 | } 36 | void func4() 37 | { 38 | cout << "Son func4..." << endl; 39 | } 40 | }; 41 | 42 | int main(void) 43 | { 44 | Base* base = new Base; 45 | base->func3(); // Base func3.... 46 | 47 | cout << "----------------" << endl; 48 | 49 | Son* son = new Son; 50 | son->fun1(); // Son func1.... 51 | son->fun2(); // Son func2.... 52 | son->func3(); // Son func3.... 53 | son->func4(); // Son func4... 54 | 55 | cout << "------------------" << endl; 56 | 57 | base = son; 58 | base->fun1(); // Son func1.... 59 | base->fun2(); // Son func2.... 60 | base->func3(); // Base func3.... 61 | //base->func4(); // error 62 | 63 | cout << "----------------" << endl; 64 | 65 | Son* son2 = dynamic_cast(base); 66 | son2->fun1(); // Son func1.... 67 | son2->fun2(); // Son func2.... 68 | son2->func3(); // son func3.... 69 | son2->func4(); // Son func4... 70 | 71 | cout << "----------------" << endl; 72 | 73 | Base* base2 = nullptr; 74 | base2 = dynamic_cast(son); 75 | base2->fun1(); // Son func1.... 76 | base2->fun2(); // Son func2.... 77 | base2->func3(); // Base func3.... 78 | //base2->func4(); // error 79 | 80 | return 0; 81 | } -------------------------------------------------------------------------------- /01.C++基础部分/src/116.vptr2.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hujiese/cpp-study/c94ec4adf61a059e7e768cabc2bcb7b276327bd6/01.C++基础部分/src/116.vptr2.cpp -------------------------------------------------------------------------------- /01.C++基础部分/src/12.sizeof_dtor_ctor_func_class.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | class CBox{ 4 | public: 5 | CBox(){}; 6 | ~CBox(){}; 7 | }; 8 | int main(){ 9 | CBox boxobj; 10 | cout << sizeof(boxobj) << endl; 11 | return 0; 12 | } 13 | -------------------------------------------------------------------------------- /01.C++基础部分/src/120.virtual_extens.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | class A{ 5 | public: 6 | void doIt(){ cout << "A ..." << endl; } 7 | }; 8 | class B :public virtual A{}; 9 | class C : public virtual A{}; 10 | class D :public B, public C{}; 11 | 12 | int main() 13 | { 14 | int a, b, c, d; 15 | 16 | a = sizeof(A); 17 | b = sizeof(B); 18 | c = sizeof(C); 19 | d = sizeof(D); 20 | 21 | cout << a << b << c << d << endl; // 1448 22 | 23 | A aa; 24 | B bb; 25 | C cc; 26 | D dd; 27 | 28 | aa.doIt(); // A ... 29 | bb.doIt(); // A ... 30 | cc.doIt(); // A ... 31 | dd.doIt(); // A ... 32 | 33 | return 0; 34 | } 35 | -------------------------------------------------------------------------------- /01.C++基础部分/src/121.vector_resize_reverse.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hujiese/cpp-study/c94ec4adf61a059e7e768cabc2bcb7b276327bd6/01.C++基础部分/src/121.vector_resize_reverse.cpp -------------------------------------------------------------------------------- /01.C++基础部分/src/123.vector_swap.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hujiese/cpp-study/c94ec4adf61a059e7e768cabc2bcb7b276327bd6/01.C++基础部分/src/123.vector_swap.cpp -------------------------------------------------------------------------------- /01.C++基础部分/src/128.moveCopy.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | using namespace std; 4 | 5 | class Object 6 | { 7 | public: 8 | Object() { 9 | std::cout << "Object()" << std::endl; 10 | } 11 | ~Object(){ 12 | } 13 | 14 | Object(const Object& object) { 15 | std::cout << "Object(const Object&)" << std::endl; 16 | } 17 | 18 | Object(const Object&& object) { 19 | std::cout << "Object(const Object&&)" << std::endl; 20 | 21 | } 22 | Object getObject(void) { 23 | Object obj; 24 | return obj; 25 | } 26 | }; 27 | 28 | int main(void) 29 | { 30 | Object o1; 31 | //Object o2 = o1.getObject(); 32 | Object o3 = move(o1); 33 | 34 | return 0; 35 | } -------------------------------------------------------------------------------- /01.C++基础部分/src/129.mutable.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hujiese/cpp-study/c94ec4adf61a059e7e768cabc2bcb7b276327bd6/01.C++基础部分/src/129.mutable.cpp -------------------------------------------------------------------------------- /01.C++基础部分/src/13.sizeof_of_vdtor_class.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | class CBox{ 4 | public: 5 | CBox(){}; 6 | virtual ~CBox(){}; 7 | }; 8 | int main(){ 9 | CBox boxobj; 10 | cout << sizeof(boxobj) << endl;//4 11 | return 0; 12 | } 13 | -------------------------------------------------------------------------------- /01.C++基础部分/src/14.sizeof_extends_class.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | class A{ 4 | }; 5 | class B{ 6 | }; 7 | class C :public A{ 8 | }; 9 | class D :public virtual B{ 10 | }; 11 | class E :public A, public B{ 12 | }; 13 | int main(){ 14 | A a; 15 | B b; 16 | C c; 17 | D d; 18 | E e; 19 | cout << "sizeof(a):" << sizeof(a) << endl; 20 | cout << "sizeof(b):" << sizeof(b) << endl; 21 | cout << "sizeof(c):" << sizeof(c) << endl; 22 | cout << "sizeof(d):" << sizeof(d) << endl; 23 | cout << "sizeof(e):" << sizeof(e) << endl; 24 | return 0; 25 | } 26 | -------------------------------------------------------------------------------- /01.C++基础部分/src/15.virtual_function.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | class Father{ 4 | public: 5 | virtual void print() 6 | { 7 | cout << "Father's print ...." << endl; 8 | } 9 | 10 | void printX() 11 | { 12 | cout << "Father's printX ...." << endl; 13 | } 14 | }; 15 | class Son : public Father 16 | { 17 | public: 18 | virtual void print() 19 | { 20 | cout << "Son's print ...." << endl; 21 | } 22 | 23 | void printX() 24 | { 25 | cout << "Son's printX ...." << endl; 26 | } 27 | 28 | void prntY() 29 | { 30 | cout << "Son's printY ...." << endl; 31 | } 32 | }; 33 | int main() 34 | { 35 | Father father; 36 | father.print(); 37 | father.printX(); 38 | cout << "------------------------------------" << endl; 39 | Son son; 40 | son.print(); 41 | son.printX(); 42 | son.prntY(); 43 | cout << "------------------------------------" << endl; 44 | Father* fa = &son; 45 | fa->print(); 46 | fa->printX(); 47 | //fa->printY(); //error !!! 48 | return 0; 49 | } 50 | -------------------------------------------------------------------------------- /01.C++基础部分/src/16.virtual_dtor.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hujiese/cpp-study/c94ec4adf61a059e7e768cabc2bcb7b276327bd6/01.C++基础部分/src/16.virtual_dtor.cpp -------------------------------------------------------------------------------- /01.C++基础部分/src/17.function_template.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hujiese/cpp-study/c94ec4adf61a059e7e768cabc2bcb7b276327bd6/01.C++基础部分/src/17.function_template.cpp -------------------------------------------------------------------------------- /01.C++基础部分/src/18.static_cast.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | int main(void) 5 | { 6 | double dPi = 3.1415926; 7 | int num1 = (int)dPi; //c语言的旧式类型转换 8 | int num2 = dPi; //隐式类型转换 9 | // 静态的类型转换: 10 | // 在编译的时 进⾏行基本类型的转换 能替代c⻛风格的类型转换 可以进⾏行⼀一部分检查 11 | int num3 = static_cast (dPi); //c++的新式的类型转换运算符 12 | cout << "num1:" << num1 << " num2:" << num2 << " num3:" << num3 << endl;// num1:3 num2:3 num3:3 13 | return 0; 14 | } -------------------------------------------------------------------------------- /01.C++基础部分/src/19.dynamic_cast.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | class Animal { 4 | public: 5 | virtual void cry() = 0; 6 | }; 7 | 8 | class Dog : public Animal 9 | { 10 | public: 11 | virtual void cry() 12 | { 13 | std::cout << "旺旺" << std::endl; 14 | } 15 | void dohome() 16 | { 17 | std::cout << "看家" << std::endl; 18 | } 19 | }; 20 | 21 | class Cat : public Animal 22 | { 23 | public: 24 | virtual void cry() 25 | { 26 | std::cout << "喵喵" << std::endl; 27 | } 28 | void dohome() 29 | { 30 | std::cout << "抓老鼠" << std::endl; 31 | } 32 | }; 33 | 34 | int main() 35 | { 36 | Animal* base = NULL; 37 | base = new Cat(); 38 | base->cry();// 喵喵 39 | 40 | std::cout << "--------------------" << std::endl; 41 | //⽤用于将⽗父类指针转换成⼦子类, 42 | Dog *pDog = dynamic_cast(base); //此时转换时失败的,因为父类指针现在指向的对象是猫,所以转换狗是失败的。 43 | //转换失败返回空(NULL) 44 | if (pDog != NULL) 45 | { 46 | pDog->cry(); 47 | pDog->dohome(); 48 | } 49 | std::cout << "--------------------" << std::endl; 50 | Cat* pCat = dynamic_cast(base); //此时转换成功,成功将父类指针转换成子类指针 51 | if (pCat != NULL) 52 | { 53 | pCat->cry();// 喵喵 54 | pCat->dohome();// 抓老鼠 55 | } 56 | 57 | system("pause"); 58 | return 0; 59 | } 60 | -------------------------------------------------------------------------------- /01.C++基础部分/src/20.const_cast.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hujiese/cpp-study/c94ec4adf61a059e7e768cabc2bcb7b276327bd6/01.C++基础部分/src/20.const_cast.cpp -------------------------------------------------------------------------------- /01.C++基础部分/src/21.reinterpret_cast.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hujiese/cpp-study/c94ec4adf61a059e7e768cabc2bcb7b276327bd6/01.C++基础部分/src/21.reinterpret_cast.cpp -------------------------------------------------------------------------------- /01.C++基础部分/src/99.sturct2.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hujiese/cpp-study/c94ec4adf61a059e7e768cabc2bcb7b276327bd6/01.C++基础部分/src/99.sturct2.cpp -------------------------------------------------------------------------------- /02.C++11/README.md: -------------------------------------------------------------------------------- 1 | ## C++ 11 2 | 3 | ### lambda表达式 4 | ### 函数绑定 5 | ### 智能指针 6 | ### 并发编程 7 | ### 其他 -------------------------------------------------------------------------------- /02.C++11/lambda表达式/README.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | - [lambda表达式](#lambda%E8%A1%A8%E8%BE%BE%E5%BC%8F) 5 | - [一、声明Lambda表达式](#%E4%B8%80%E5%A3%B0%E6%98%8Elambda%E8%A1%A8%E8%BE%BE%E5%BC%8F) 6 | - [二、捕获外部变量](#%E4%BA%8C%E6%8D%95%E8%8E%B7%E5%A4%96%E9%83%A8%E5%8F%98%E9%87%8F) 7 | - [1、值捕获](#1%E5%80%BC%E6%8D%95%E8%8E%B7) 8 | - [2、引用捕获](#2%E5%BC%95%E7%94%A8%E6%8D%95%E8%8E%B7) 9 | - [3、隐式捕获](#3%E9%9A%90%E5%BC%8F%E6%8D%95%E8%8E%B7) 10 | - [4、混合方式](#4%E6%B7%B7%E5%90%88%E6%96%B9%E5%BC%8F) 11 | - [三、修改捕获变量](#%E4%B8%89%E4%BF%AE%E6%94%B9%E6%8D%95%E8%8E%B7%E5%8F%98%E9%87%8F) 12 | - [四、Lambda表达式的参数](#%E5%9B%9Blambda%E8%A1%A8%E8%BE%BE%E5%BC%8F%E7%9A%84%E5%8F%82%E6%95%B0) 13 | 14 | 15 | 16 | ## lambda表达式 17 | 18 | 本文参考 [C++ 11 Lambda表达式](https://www.cnblogs.com/DswCnblog/p/5629165.html) 19 | 20 | C++11引入了Lambda表达式。利用Lambda表达式,可以方便的定义和创建匿名函数。很多高级语言在很早以前就已经提供了Lambda表达式的功能。 21 | 22 | ### 一、声明Lambda表达式 23 | 24 | Lambda表达式完整的声明格式如下: 25 | ```c 26 | [capture list] (params list) mutable exception-> return_type { function body } 27 | ``` 28 | 各项具体含义如下: 29 | 30 | * capture list:捕获外部变量列表 31 | * params list:形参列表 32 | * mutable指示符:用来说用是否可以修改捕获的变量 33 | * exception:异常设定 34 | * return type:返回类型 35 | * function body:函数体 36 | 37 | 此外,我们还可以省略其中的某些成分来声明“不完整”的Lambda表达式,常见的有以下几种: 38 | 39 | 序号|格式 40 | ---|--- 41 | 1 | [capture list] (params list) -> return_type {function body} 42 | 2 | [capture list] (params list) {function body} 43 | 3 | [capture list] {function body} 44 | 45 | 其中: 46 | 47 | * 格式1声明了const类型的表达式,这种类型的表达式不能修改捕获列表中的值。 48 | * 格式2省略了返回值类型,但编译器可以根据以下规则推断出Lambda表达式的返回类型: 49 | 50 | * (1)如果function body中存在return语句,则该Lambda表达式的返回类型由return语句的返回类型确定; 51 | * (2)如果function body中没有return语句,则返回值为void类型。 52 | * 格式3中省略了参数列表,类似普通函数中的无参函数。 53 | 54 | 下面举一个实例: 55 | ```c 56 | #include 57 | #include 58 | #include 59 | using namespace std; 60 | 61 | bool cmp(int a, int b) 62 | { 63 | return a < b; 64 | } 65 | 66 | int main() 67 | { 68 | vector myvec{ 3, 2, 5, 7, 3, 2 }; 69 | vector lbvec(myvec); 70 | 71 | sort(myvec.begin(), myvec.end(), cmp); // 旧式做法 72 | cout << "predicate function:" << endl; 73 | for (int it : myvec) 74 | cout << it << ' '; 75 | cout << endl; 76 | 77 | sort(lbvec.begin(), lbvec.end(), [](int a, int b) -> bool { return a < b; }); // Lambda表达式 78 | cout << "lambda expression:" << endl; 79 | for (int it : lbvec) 80 | cout << it << ' '; 81 | cout << endl; 82 | } 83 | ``` 84 | 运行结果如下: 85 | ``` 86 | predicate function: 87 | 2 2 3 3 5 7 88 | lambda expression: 89 | 2 2 3 3 5 7 90 | ``` 91 | 在C++11之前使用STL的sort函数,需要提供一个谓词函数。如果使用C++11的Lambda表达式,我们只需要传入一个匿名函数即可,方便简洁,而且代码的可读性也比旧式的做法好多了。 92 | 93 | 接下来将重点介绍一下Lambda表达式各项的具体用法。 94 | 95 | ### 二、捕获外部变量 96 | 97 | Lambda表达式可以使用其可见范围内的外部变量,但必须明确声明(明确声明哪些外部变量可以被该Lambda表达式使用)。那么,在哪里指定这些外部变量呢?Lambda表达式通过在最前面的方括号[]来明确指明其内部可以访问的外部变量,这一过程也称过Lambda表达式“捕获”了外部变量: 98 | 99 | ```c 100 | #include 101 | using namespace std; 102 | 103 | int main() 104 | { 105 | int a = 123; 106 | auto f = [a] { cout << a << endl; }; 107 | f(); // 输出:123 108 | 109 | //或通过“函数体”后面的‘()’传入参数 110 | [](int a){cout << a << endl; }(1233435); 111 | } 112 | ``` 113 | 运行结果如下: 114 | ``` 115 | 123 116 | 1233435 117 | ``` 118 | 上面这个例子先声明了一个整型变量a,然后再创建Lambda表达式,该表达式“捕获”了a变量,这样在Lambda表达式函数体中就可以获得该变量的值。 119 | 120 | 类似参数传递方式(值传递、引入传递、指针传递),在Lambda表达式中,外部变量的捕获方式也有值捕获、引用捕获、隐式捕获。 121 | 122 | #### 1、值捕获 123 | 124 | 值捕获和参数传递中的值传递类似,被捕获的变量的值在Lambda表达式创建时通过值拷贝的方式传入,因此随后对该变量的修改不会影响影响Lambda表达式中的值: 125 | ```c 126 | #include 127 | using namespace std; 128 | 129 | int main() 130 | { 131 | int a = 123; 132 | auto f = [a] { cout << a << endl; }; 133 | a = 321; 134 | f(); // 输出:123 135 | } 136 | ``` 137 | 这里需要注意的是,如果以传值方式捕获外部变量,则在Lambda表达式函数体中不能修改该外部变量的值。 138 | 139 | #### 2、引用捕获 140 | 141 | 使用引用捕获一个外部变量,只需要在捕获列表变量前面加上一个引用说明符&。如下: 142 | 143 | ```c 144 | #include 145 | using namespace std; 146 | 147 | int main() 148 | { 149 | int a = 123; 150 | auto f = [&a] { cout << a << endl; }; 151 | a = 321; 152 | f(); // 输出:321 153 | } 154 | ``` 155 | 从示例中可以看出,引用捕获的变量使用的实际上就是该引用所绑定的对象。 156 | 157 | #### 3、隐式捕获 158 | 159 | 上面的值捕获和引用捕获都需要我们在捕获列表中显示列出Lambda表达式中使用的外部变量。除此之外,我们还可以让编译器根据函数体中的代码来推断需要捕获哪些变量,这种方式称之为隐式捕获。隐式捕获有两种方式,分别是[=]和[&]。[=]表示以值捕获的方式捕获外部变量,[&]表示以引用捕获的方式捕获外部变量。 160 | 161 | 隐式值捕获示例: 162 | ```c 163 | int main() 164 | { 165 | int a = 123; 166 | auto f = [=] { cout << a << endl; }; // 值捕获 167 | f(); // 输出:123 168 | } 169 | ``` 170 | 隐式引用捕获示例: 171 | 172 | ```c 173 | int main() 174 | { 175 | int a = 123; 176 | auto f = [&] { cout << a << endl; }; // 引用捕获 177 | a = 321; 178 | f(); // 输出:321 179 | } 180 | ``` 181 | #### 4、混合方式 182 | 183 | 上面的例子,要么是值捕获,要么是引用捕获,Lambda表达式还支持混合的方式捕获外部变量,这种方式主要是以上几种捕获方式的组合使用。 184 | 185 | 到这里,我们来总结一下:C++11中的Lambda表达式捕获外部变量主要有以下形式: 186 | 187 | 捕获形式| 说明 188 | ---|--- 189 | []| 不捕获任何外部变量 190 | [变量名, …] | 默认以值得形式捕获指定的多个外部变量(用逗号分隔),如果引用捕获,需要显示声明(使用&说明符) 191 | [this]| 以值的形式捕获this指针 192 | [=]| 以值的形式捕获所有外部变量 193 | [&] |以引用形式捕获所有外部变量 194 | [=, &x] |变量x以引用形式捕获,其余变量以传值形式捕获 195 | [&, x] |变量x以值的形式捕获,其余变量以引用形式捕获 196 | 197 | ### 三、修改捕获变量 198 | 199 | 前面提到过,在Lambda表达式中,如果以传值方式捕获外部变量,则函数体中不能修改该外部变量,否则会引发编译错误。那么有没有办法可以修改值捕获的外部变量呢?这是就需要使用mutable关键字,该关键字用以说明表达式体内的代码可以修改值捕获的变量: 200 | 201 | ```c 202 | int main() 203 | { 204 | int a = 123; 205 | auto f = [a]()mutable { cout << ++a; }; // 不会报错 206 | cout << a << endl; // 输出:123 207 | f(); // 输出:124 208 | } 209 | ``` 210 | 211 | 如果不想使用mutable关键字,可以采取引用方式捕获外部变量,而非传值。 212 | 213 | ### 四、Lambda表达式的参数 214 | 215 | Lambda表达式的参数和普通函数的参数类似,那么这里为什么还要拿出来说一下呢?原因是在Lambda表达式中传递参数还有一些限制,主要有以下几点: 216 | 217 | * 参数列表中不能有默认参数 218 | * 不支持可变参数 219 | * 所有参数必须有参数名 -------------------------------------------------------------------------------- /02.C++11/lambda表达式/src/22.lambda.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hujiese/cpp-study/c94ec4adf61a059e7e768cabc2bcb7b276327bd6/02.C++11/lambda表达式/src/22.lambda.cpp -------------------------------------------------------------------------------- /02.C++11/lambda表达式/src/23.lambda2.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hujiese/cpp-study/c94ec4adf61a059e7e768cabc2bcb7b276327bd6/02.C++11/lambda表达式/src/23.lambda2.cpp -------------------------------------------------------------------------------- /02.C++11/函数绑定/README.md: -------------------------------------------------------------------------------- 1 | ## 函数绑定 2 | 3 | 看完下面这个案例,函数绑定的使用便基本掌握了: 4 | ```c 5 | #include 6 | #include 7 | using namespace std; 8 | 9 | typedef function Fun; 10 | typedef function Fun2; 11 | 12 | class Foo 13 | { 14 | public: 15 | void memberFunc(double d, int i, int j) 16 | { 17 | cout << d << endl; 18 | cout << i << endl; 19 | cout << j << endl; 20 | } 21 | }; 22 | 23 | void memberFunc(double d, int i, int j) 24 | { 25 | cout << d << endl; 26 | cout << i << endl; 27 | cout << j << endl; 28 | } 29 | 30 | int Func(int i, int j) 31 | { 32 | return i + j; 33 | } 34 | 35 | int main() 36 | { 37 | Foo foo; 38 | function fp = bind(&Foo::memberFunc, &foo, 0.5, placeholders::_1, placeholders::_2); 39 | fp(100, 200); 40 | cout << "---------------------------" << endl; 41 | 42 | function fp2 = bind(&Foo::memberFunc, ref(foo), 0.5, placeholders::_1, placeholders::_2); 43 | fp2(55, 66); 44 | cout << "---------------------------" << endl; 45 | 46 | Fun fun = bind(memberFunc, 0.3, placeholders::_1, placeholders::_2); 47 | fun(123, 456); 48 | cout << "---------------------------" << endl; 49 | 50 | Fun2 fun2 = bind(memberFunc, 0.5, 666, placeholders::_1); 51 | fun2(77); 52 | cout << "---------------------------" << endl; 53 | 54 | Fun2 fun3 = bind(memberFunc, 0.5, placeholders::_1, 666); 55 | fun3(77); 56 | cout << "---------------------------" << endl; 57 | 58 | function fun4 = bind(Func, placeholders::_1, placeholders::_2); 59 | int temp = fun4(1, 2); 60 | cout << temp << endl; 61 | 62 | return 0; 63 | } 64 | ``` 65 | 该案例运行结果如下: 66 | ``` 67 | 0.5 68 | 100 69 | 200 70 | --------------------------- 71 | 0.5 72 | 55 73 | 66 74 | --------------------------- 75 | 0.3 76 | 123 77 | 456 78 | --------------------------- 79 | 0.5 80 | 666 81 | 77 82 | --------------------------- 83 | 0.5 84 | 77 85 | 666 86 | --------------------------- 87 | 3 88 | ``` -------------------------------------------------------------------------------- /02.C++11/函数绑定/src/24.bind_function.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | using namespace std; 4 | 5 | typedef function Fun; 6 | typedef function Fun2; 7 | 8 | class Foo 9 | { 10 | public: 11 | void memberFunc(double d, int i, int j) 12 | { 13 | cout << d << endl; 14 | cout << i << endl; 15 | cout << j << endl; 16 | } 17 | }; 18 | 19 | void memberFunc(double d, int i, int j) 20 | { 21 | cout << d << endl; 22 | cout << i << endl; 23 | cout << j << endl; 24 | } 25 | 26 | int Func(int i, int j) 27 | { 28 | return i + j; 29 | } 30 | 31 | int main() 32 | { 33 | Foo foo; 34 | function fp = bind(&Foo::memberFunc, &foo, 0.5, placeholders::_1, placeholders::_2); 35 | fp(100, 200); 36 | cout << "---------------------------" << endl; 37 | 38 | function fp2 = bind(&Foo::memberFunc, ref(foo), 0.5, placeholders::_1, placeholders::_2); 39 | fp2(55, 66); 40 | cout << "---------------------------" << endl; 41 | 42 | Fun fun = bind(memberFunc, 0.3, placeholders::_1, placeholders::_2); 43 | fun(123, 456); 44 | cout << "---------------------------" << endl; 45 | 46 | Fun2 fun2 = bind(memberFunc, 0.5, 666, placeholders::_1); 47 | fun2(77); 48 | cout << "---------------------------" << endl; 49 | 50 | Fun2 fun3 = bind(memberFunc, 0.5, placeholders::_1, 666); 51 | fun3(77); 52 | cout << "---------------------------" << endl; 53 | 54 | function fun4 = bind(Func, placeholders::_1, placeholders::_2); 55 | int temp = fun4(1, 2); 56 | cout << temp << endl; 57 | 58 | return 0; 59 | } -------------------------------------------------------------------------------- /02.C++11/可变参数/README.md: -------------------------------------------------------------------------------- 1 | ## 可变参数 2 | 3 | 来自 [泛化之美--C++11可变模版参数的妙用](https://www.cnblogs.com/qicosmos/p/4325949.html) 4 | 5 | ![](./img/args.png) 6 | 7 | -------------------------------------------------------------------------------- /02.C++11/可变参数/img/args.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hujiese/cpp-study/c94ec4adf61a059e7e768cabc2bcb7b276327bd6/02.C++11/可变参数/img/args.png -------------------------------------------------------------------------------- /02.C++11/右值与完美转发/README.md: -------------------------------------------------------------------------------- 1 | ## 右值与完美转发 2 | 3 | 来自 [从4行代码看右值引用](https://www.cnblogs.com/qicosmos/p/4283455.html) 4 | 5 | ![从4行代码看右值引用](./img/&&.png) 6 | -------------------------------------------------------------------------------- /02.C++11/右值与完美转发/img/&&.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hujiese/cpp-study/c94ec4adf61a059e7e768cabc2bcb7b276327bd6/02.C++11/右值与完美转发/img/&&.png -------------------------------------------------------------------------------- /02.C++11/并发编程/01.多线程编程/README.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | - [C++11 多线程编程](#c11-%E5%A4%9A%E7%BA%BF%E7%A8%8B%E7%BC%96%E7%A8%8B) 6 | - [一、创建线程](#%E4%B8%80%E5%88%9B%E5%BB%BA%E7%BA%BF%E7%A8%8B) 7 | - [1、线程分离](#1%E7%BA%BF%E7%A8%8B%E5%88%86%E7%A6%BB) 8 | - [2、线程函数是仿函数](#2%E7%BA%BF%E7%A8%8B%E5%87%BD%E6%95%B0%E6%98%AF%E4%BB%BF%E5%87%BD%E6%95%B0) 9 | - [3、线程函数是lambda表达式](#3%E7%BA%BF%E7%A8%8B%E5%87%BD%E6%95%B0%E6%98%AFlambda%E8%A1%A8%E8%BE%BE%E5%BC%8F) 10 | - [二、线程传递参数](#%E4%BA%8C%E7%BA%BF%E7%A8%8B%E4%BC%A0%E9%80%92%E5%8F%82%E6%95%B0) 11 | - [1、普通传参](#1%E6%99%AE%E9%80%9A%E4%BC%A0%E5%8F%82) 12 | - [2、传递引用](#2%E4%BC%A0%E9%80%92%E5%BC%95%E7%94%A8) 13 | - [3、使用move函数实现零拷贝传参](#3%E4%BD%BF%E7%94%A8move%E5%87%BD%E6%95%B0%E5%AE%9E%E7%8E%B0%E9%9B%B6%E6%8B%B7%E8%B4%9D%E4%BC%A0%E5%8F%82) 14 | - [三、线程拷贝](#%E4%B8%89%E7%BA%BF%E7%A8%8B%E6%8B%B7%E8%B4%9D) 15 | - [四、线程信息](#%E5%9B%9B%E7%BA%BF%E7%A8%8B%E4%BF%A1%E6%81%AF) 16 | - [1、线程ID](#1%E7%BA%BF%E7%A8%8Bid) 17 | - [2、查看CPU有多少线程](#2%E6%9F%A5%E7%9C%8Bcpu%E6%9C%89%E5%A4%9A%E5%B0%91%E7%BA%BF%E7%A8%8B) 18 | - [五、多线程与lambda表达式](#%E4%BA%94%E5%A4%9A%E7%BA%BF%E7%A8%8B%E4%B8%8Elambda%E8%A1%A8%E8%BE%BE%E5%BC%8F) 19 | - [1、创建五个lambda线程](#1%E5%88%9B%E5%BB%BA%E4%BA%94%E4%B8%AAlambda%E7%BA%BF%E7%A8%8B) 20 | - [2、打印循环创建的线程编号](#2%E6%89%93%E5%8D%B0%E5%BE%AA%E7%8E%AF%E5%88%9B%E5%BB%BA%E7%9A%84%E7%BA%BF%E7%A8%8B%E7%BC%96%E5%8F%B7) 21 | 22 | 23 | 24 | ## C++11 多线程编程 25 | 26 | 本文参考 [C++11/C++14 THREAD 1. CREATING THREADS](https://www.bogotobogo.com/cplusplus/C11/1_C11_creating_thread.php) 27 | 28 | 在看这一些列文章前最好有过Linux多线程编程经验,对于很多常识性的东西(例如join和线程分离,这里不会做过多介绍)。 29 | 30 | ### 一、创建线程 31 | 32 | 创建一个线程在C++11中是个简单的事,下面这个例子演示了如何创建线程: 33 | ```c 34 | #include 35 | #include 36 | 37 | void thread_function() 38 | { 39 | std::cout << "thread function\n"; 40 | } 41 | 42 | int main() 43 | { 44 | std::thread t(&thread_function); // t starts running 45 | //std::thread t(thread_function); 46 | std::cout << "main thread\n"; 47 | t.join(); // main thread waits for the thread t to finish 48 | return 0; 49 | } 50 | ``` 51 | 运行结果如下: 52 | ``` 53 | thread function 54 | main thread 55 | ``` 56 | 57 | #### 1、线程分离 58 | 59 | 线程分离代码如下: 60 | ```c 61 | #include 62 | #include 63 | 64 | void thread_function() 65 | { 66 | std::cout << "thread function\n"; 67 | } 68 | 69 | int main() 70 | { 71 | std::thread t(&thread_function); 72 | std::cout << "main thread\n"; 73 | // t.join(); 74 | t.detach(); 75 | return 0; 76 | } 77 | ``` 78 | 使用detach函数实现线程分离,分离后的现场会成为一个后台程序,和之前的主线程没有任何关系。需要注意的是,一个线程一旦被设置为“分离”,那么就不能在主线程中使用join等待该子线程退出。判断一个线程是否能join,可以使用函数joinable,下面是使用的案例: 79 | ```c 80 | #include 81 | #include 82 | 83 | void thread_function() 84 | { 85 | std::cout << "thread function\n"; 86 | } 87 | 88 | int main() 89 | { 90 | std::thread t(&thread_function); 91 | std::cout << "main thread\n"; 92 | t.detach(); 93 | if (t.joinable()) 94 | { 95 | std::cout << "joinable" << std::endl; 96 | } 97 | else 98 | { 99 | std::cout << "no join" << std::endl; 100 | } 101 | return 0; 102 | } 103 | ``` 104 | 运行结果如下: 105 | ``` 106 | thread function 107 | main thread 108 | no join 109 | ``` 110 | 111 | #### 2、线程函数是仿函数 112 | 113 | 前面的std::thread传入的参数是一个函数地址,当然也可以传入一个仿函数: 114 | ```c 115 | #include 116 | #include 117 | 118 | class MyFunctor 119 | { 120 | public: 121 | void operator()() { 122 | std::cout << "functor\n"; 123 | } 124 | }; 125 | 126 | int main() 127 | { 128 | MyFunctor fnctor; 129 | std::thread t(fnctor); 130 | std::cout << "main thread\n"; 131 | t.join(); 132 | return 0; 133 | } 134 | ``` 135 | 有可能会将一个临时仿函数对象传给一个线程: 136 | ```c 137 | std::thread t(MyFunctor()); 138 | ``` 139 | 但这样做编译会报错,应该这样写: 140 | ```c 141 | std::thread t((MyFunctor())); 142 | ``` 143 | 144 | #### 3、线程函数是lambda表达式 145 | 146 | ```c 147 | #include 148 | #include 149 | 150 | int main() 151 | { 152 | std::thread t([]() 153 | { 154 | std::cout << "thread function\n"; 155 | } 156 | ); 157 | std::cout << "main thread\n"; 158 | t.join(); // main thread waits for t to finish 159 | return 0; 160 | } 161 | ``` 162 | 163 | ### 二、线程传递参数 164 | 165 | #### 1、普通传参 166 | 167 | 如果向一个线程传递一个普通的变量,可以参考下面这种做法: 168 | 169 | ```c 170 | #include 171 | #include 172 | #include 173 | 174 | void thread_function(std::string s) 175 | { 176 | std::cout << "thread function "; 177 | std::cout << "message is = " << s << std::endl; 178 | } 179 | 180 | int main() 181 | { 182 | std::string s = "Kathy Perry"; 183 | std::thread t(&thread_function, s); 184 | std::cout << "main thread message = " << s << std::endl; 185 | t.join(); 186 | return 0; 187 | } 188 | ``` 189 | #### 2、传递引用 190 | 191 | 有时候也需要向线程传递一个引用,很多人可能会采用如下方法来传递引用: 192 | ```c 193 | void thread_function(std::string &s) 194 | { 195 | std::cout << "thread function "; 196 | std::cout << "message is = " << s << std::endl; 197 | s = "Justin Beaver"; 198 | } 199 | 200 | ... 201 | std::thread t(&thread_function, s); 202 | ``` 203 | 但这种做法是错误的,它不能达到想要的结果--改变s的值并在main函数中打印这个修改过后的值。 204 | 205 | 如果想要真的传递引用,还得使用如下方法来创建线程: 206 | ```c 207 | std::thread t(&thread;_function, std::ref(s)); 208 | ``` 209 | 完整代码如下所示: 210 | ```c 211 | #include 212 | #include 213 | #include 214 | 215 | void thread_function(std::string &s) 216 | { 217 | std::cout << "thread function "; 218 | std::cout << "message is = " << s << std::endl; 219 | s = "Justin Beaver"; 220 | } 221 | 222 | int main() 223 | { 224 | std::string s = "Kathy Perry"; 225 | /*std::thread t(&thread_function, s);*/ 226 | std::thread t(&thread_function, std::ref(s)); 227 | t.join(); 228 | std::cout << "main thread message = " << s << std::endl; 229 | return 0; 230 | } 231 | ``` 232 | 输出结果如下: 233 | ``` 234 | thread function message is = Kathy Perry 235 | main thread message = Justin Beaver 236 | ``` 237 | 238 | #### 3、使用move函数实现零拷贝传参 239 | 240 | 除前面说的一些传递参数方法之外,也可以通过move函数来传递参数,这种方式将实现参数传递的“零拷贝”: 241 | ```c 242 | #include 243 | #include 244 | #include 245 | 246 | void thread_function(std::string s) 247 | { 248 | std::cout << "thread function "; 249 | std::cout << "message is = " << s << std::endl; 250 | } 251 | 252 | int main() 253 | { 254 | std::string s = "Kathy Perry"; 255 | std::thread t(&thread_function, std::move(s)); 256 | t.join(); 257 | std::cout << "main thread message = " << s << std::endl; 258 | return 0; 259 | } 260 | ``` 261 | 运行结果如下: 262 | ``` 263 | thread function message is = Kathy Perry 264 | main thread message = 265 | ``` 266 | 267 | ### 三、线程拷贝 268 | 269 | 使用=赋值方式拷贝线程是不允许的: 270 | ```c 271 | #include 272 | #include 273 | 274 | void thread_function() 275 | { 276 | std::cout << "thread function\n"; 277 | } 278 | 279 | int main() 280 | { 281 | std::thread t(&thread_function); 282 | std::cout << "main thread\n"; 283 | std::thread t2 = t;// 错误 1 error C2280: “std::thread::thread(const std::thread &)”: 尝试引用已删除的函数 284 | // std::thread t2 = move(t); 285 | t2.join(); 286 | 287 | return 0; 288 | } 289 | ``` 290 | 如果非得拷贝或者转移一个线程,还是得使用move函数: 291 | ```c 292 | std::thread t2 = move(t); 293 | ``` 294 | ### 四、线程信息 295 | 296 | #### 1、线程ID 297 | 298 | 可以通过下面方法来获取线程id: 299 | ```c 300 | #include 301 | #include 302 | 303 | void thread_function() 304 | { 305 | std::cout << "thread function id is " << std::this_thread::get_id() << std::endl;; 306 | } 307 | int main() 308 | { 309 | std::thread t(&thread_function); 310 | std::cout << "child thread id = " << t.get_id() << std::endl; 311 | 312 | t.join(); 313 | std::cout << "main thread id = " << std::this_thread::get_id() << std::endl; 314 | return 0; 315 | } 316 | ``` 317 | 运行结果如下: 318 | ``` 319 | thread function id is child thread id = 3096 320 | 3096 321 | main thread id = 8228 322 | ``` 323 | 324 | #### 2、查看CPU有多少线程 325 | 326 | ```c 327 | #include 328 | #include 329 | 330 | int main() 331 | { 332 | std::cout << "A Number of threads = " << std::thread::hardware_concurrency() << std::endl; 333 | return 0; 334 | } 335 | ``` 336 | 运行结果如下: 337 | ``` 338 | A Number of threads = 8 339 | ``` 340 | 我的CPU是四核八线程,所以打印结果是8。 341 | 342 | ### 五、多线程与lambda表达式 343 | 344 | 之前通过lambda创建过多线程程序,但只创建了一个线程而已,下面将深入lambda和多线程程序的结合。 345 | 346 | #### 1、创建五个lambda线程 347 | 348 | 下面将循环创建五个线程,这几个线程会保存到一个vector数组中: 349 | ```c 350 | #include 351 | #include 352 | #include 353 | #include 354 | 355 | int main() 356 | { 357 | // vector container stores threads 358 | std::vector workers; 359 | for (int i = 0; i < 5; i++) { 360 | workers.push_back(std::thread([]() 361 | { 362 | std::cout << "thread function\n"; 363 | })); 364 | } 365 | std::cout << "main thread\n"; 366 | 367 | // Looping every thread via for_each 368 | // The 3rd argument assigns a task 369 | // It tells the compiler we're using lambda ([]) 370 | // The lambda function takes its argument as a reference to a thread, t 371 | // Then, joins one by one, and this works like barrier 372 | std::for_each(workers.begin(), workers.end(), [](std::thread &t) 373 | { 374 | t.join(); 375 | }); 376 | 377 | return 0; 378 | } 379 | ``` 380 | 运行结果如下: 381 | ``` 382 | thread function 383 | thread function 384 | thread function 385 | thread function 386 | thread function 387 | main thread 388 | ``` 389 | #### 2、打印循环创建的线程编号 390 | 391 | 上面的例子的确创建了五个线程,而且运行函数是lambda表达式,但是我们并不知道哪个线程会先运行,如果想要知道当前运行的是哪个线程,可以传递创建线程是i的值,以此标记线程: 392 | ```c 393 | for (int i = 0; i < 5; i++) { 394 | workers.push_back(std::thread([i]() 395 | { 396 | std::cout << "thread function " << i << "\n"; 397 | })); 398 | } 399 | ``` 400 | 运行结果如下: 401 | ```thread function thread function 1 402 | thread function 4 403 | thread function 2 404 | 0 405 | main thread 406 | thread function 3 407 | ``` -------------------------------------------------------------------------------- /02.C++11/并发编程/01.多线程编程/src/33.thread_create.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | void thread_function() 5 | { 6 | std::cout << "thread function\n"; 7 | } 8 | 9 | int main() 10 | { 11 | std::thread t(&thread_function); // t starts running 12 | //std::thread t(thread_function); 13 | std::cout << "main thread\n"; 14 | t.join(); // main thread waits for the thread t to finish 15 | return 0; 16 | } -------------------------------------------------------------------------------- /02.C++11/并发编程/01.多线程编程/src/34.detech_thread.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | void thread_function() 5 | { 6 | std::cout << "thread function\n"; 7 | } 8 | 9 | int main() 10 | { 11 | std::thread t(&thread_function); 12 | std::cout << "main thread\n"; 13 | // t.join(); 14 | t.detach(); 15 | return 0; 16 | } -------------------------------------------------------------------------------- /02.C++11/并发编程/01.多线程编程/src/35.thread_joinable.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | void thread_function() 5 | { 6 | std::cout << "thread function\n"; 7 | } 8 | 9 | int main() 10 | { 11 | std::thread t(&thread_function); 12 | std::cout << "main thread\n"; 13 | t.detach(); 14 | if (t.joinable()) 15 | { 16 | std::cout << "joinable" << std::endl; 17 | } 18 | else 19 | { 20 | std::cout << "no join" << std::endl; 21 | } 22 | return 0; 23 | } -------------------------------------------------------------------------------- /02.C++11/并发编程/01.多线程编程/src/36.thread_functors.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | class MyFunctor 5 | { 6 | public: 7 | void operator()() { 8 | std::cout << "functor\n"; 9 | } 10 | }; 11 | 12 | int main() 13 | { 14 | //MyFunctor fnctor; 15 | //std::thread t(fnctor); 16 | std::thread t((MyFunctor())); 17 | //std::thread t(MyFunctor()); // error ! 18 | std::cout << "main thread\n"; 19 | t.join(); 20 | return 0; 21 | } -------------------------------------------------------------------------------- /02.C++11/并发编程/01.多线程编程/src/37.thread_lambda.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int main() 5 | { 6 | std::thread t([]() 7 | { 8 | std::cout << "thread function\n"; 9 | } 10 | ); 11 | std::cout << "main thread\n"; 12 | t.join(); // main thread waits for t to finish 13 | return 0; 14 | } -------------------------------------------------------------------------------- /02.C++11/并发编程/01.多线程编程/src/38.thread_pass_paras.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | void thread_function(std::string s) 6 | { 7 | std::cout << "thread function "; 8 | std::cout << "message is = " << s << std::endl; 9 | } 10 | 11 | int main() 12 | { 13 | std::string s = "Kathy Perry"; 14 | std::thread t(&thread_function, s); 15 | std::cout << "main thread message = " << s << std::endl; 16 | t.join(); 17 | return 0; 18 | } -------------------------------------------------------------------------------- /02.C++11/并发编程/01.多线程编程/src/39.thread_pass_ref.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | void thread_function(std::string &s) 6 | { 7 | std::cout << "thread function "; 8 | std::cout << "message is = " << s << std::endl; 9 | s = "Justin Beaver"; 10 | } 11 | 12 | int main() 13 | { 14 | std::string s = "Kathy Perry"; 15 | /*std::thread t(&thread_function, s);*/ 16 | std::thread t(&thread_function, std::ref(s)); 17 | t.join(); 18 | std::cout << "main thread message = " << s << std::endl; 19 | return 0; 20 | } -------------------------------------------------------------------------------- /02.C++11/并发编程/01.多线程编程/src/40.thread_move_paras.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | void thread_function(std::string s) 6 | { 7 | std::cout << "thread function "; 8 | std::cout << "message is = " << s << std::endl; 9 | } 10 | 11 | int main() 12 | { 13 | std::string s = "Kathy Perry"; 14 | std::thread t(&thread_function, std::move(s)); 15 | t.join(); 16 | std::cout << "main thread message = " << s << std::endl; 17 | return 0; 18 | } -------------------------------------------------------------------------------- /02.C++11/并发编程/01.多线程编程/src/41.thread_copy_move.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hujiese/cpp-study/c94ec4adf61a059e7e768cabc2bcb7b276327bd6/02.C++11/并发编程/01.多线程编程/src/41.thread_copy_move.cpp -------------------------------------------------------------------------------- /02.C++11/并发编程/01.多线程编程/src/42.thread_ID.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | void thread_function() 5 | { 6 | std::cout << "thread function id is " << std::this_thread::get_id() << std::endl;; 7 | } 8 | int main() 9 | { 10 | std::thread t(&thread_function); 11 | std::cout << "child thread id = " << t.get_id() << std::endl; 12 | 13 | t.join(); 14 | std::cout << "main thread id = " << std::this_thread::get_id() << std::endl; 15 | return 0; 16 | } 17 | -------------------------------------------------------------------------------- /02.C++11/并发编程/01.多线程编程/src/43.how_many_threads_in_cpu.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int main() 5 | { 6 | std::cout << "A Number of threads = " << std::thread::hardware_concurrency() << std::endl; 7 | return 0; 8 | } 9 | -------------------------------------------------------------------------------- /02.C++11/并发编程/01.多线程编程/src/44.threads_with_lambda.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | int main() 7 | { 8 | // vector container stores threads 9 | std::vector workers; 10 | for (int i = 0; i < 5; i++) { 11 | workers.push_back(std::thread([]() 12 | { 13 | std::cout << "thread function\n"; 14 | })); 15 | } 16 | std::cout << "main thread\n"; 17 | 18 | // Looping every thread via for_each 19 | // The 3rd argument assigns a task 20 | // It tells the compiler we're using lambda ([]) 21 | // The lambda function takes its argument as a reference to a thread, t 22 | // Then, joins one by one, and this works like barrier 23 | std::for_each(workers.begin(), workers.end(), [](std::thread &t) 24 | { 25 | t.join(); 26 | }); 27 | 28 | return 0; 29 | } -------------------------------------------------------------------------------- /02.C++11/并发编程/01.多线程编程/src/45.threads_with_lambda2.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | int main() 7 | { 8 | // vector container stores threads 9 | std::vector workers; 10 | for (int i = 0; i < 5; i++) { 11 | workers.push_back(std::thread([i]() 12 | { 13 | std::cout << "thread function " << i << "\n"; 14 | })); 15 | } 16 | std::cout << "main thread\n"; 17 | 18 | // Looping every thread via for_each 19 | // The 3rd argument assigns a task 20 | // It tells the compiler we're using lambda ([]) 21 | // The lambda function takes its argument as a reference to a thread, t 22 | // Then, joins one by one, and this works like barrier 23 | std::for_each(workers.begin(), workers.end(), [](std::thread &t) 24 | { 25 | t.join(); 26 | }); 27 | 28 | return 0; 29 | } -------------------------------------------------------------------------------- /02.C++11/并发编程/02.线程同步/src/46.thread_mutex.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | using namespace std; 7 | 8 | std::list myList; 9 | std::mutex mu; 10 | 11 | void addToList(int max, int interval) 12 | { 13 | 14 | for (int i = 0; i < max; i++) 15 | { 16 | mu.lock(); 17 | if ((i % interval) == 0) 18 | { 19 | myList.push_back(i); 20 | } 21 | mu.unlock(); 22 | } 23 | } 24 | 25 | void printList() 26 | { 27 | mu.lock(); 28 | for (auto itr = myList.begin(), end_itr = myList.end(); itr != end_itr; ++itr) { 29 | cout << *itr << ","; 30 | } 31 | mu.unlock(); 32 | } 33 | 34 | int main() 35 | { 36 | int max = 100; 37 | 38 | std::thread t1(addToList, max, 1); 39 | std::thread t2(addToList, max, 10); 40 | std::thread t3(printList); 41 | 42 | t1.join(); 43 | t2.join(); 44 | t3.join(); 45 | 46 | return 0; 47 | } -------------------------------------------------------------------------------- /02.C++11/并发编程/02.线程同步/src/47.thread_lock_guard.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | using namespace std; 8 | 9 | // a global variable 10 | std::listmyList; 11 | 12 | // a global instance of std::mutex to protect global variable 13 | std::mutex myMutex; 14 | 15 | void addToList(int max, int interval) 16 | { 17 | // the access to this function is mutually exclusive 18 | std::lock_guard guard(myMutex); 19 | for (int i = 0; i < max; i++) { 20 | if ((i % interval) == 0) myList.push_back(i); 21 | } 22 | } 23 | 24 | void printList() 25 | { 26 | // the access to this function is mutually exclusive 27 | std::lock_guard guard(myMutex); 28 | for (auto itr = myList.begin(), end_itr = myList.end(); itr != end_itr; ++itr) { 29 | cout << *itr << ","; 30 | } 31 | } 32 | 33 | int main() 34 | { 35 | int max = 100; 36 | 37 | std::thread t1(addToList, max, 1); 38 | std::thread t2(addToList, max, 10); 39 | std::thread t3(printList); 40 | 41 | t1.join(); 42 | t2.join(); 43 | t3.join(); 44 | 45 | return 0; 46 | } 47 | -------------------------------------------------------------------------------- /02.C++11/并发编程/02.线程同步/src/48.thread_safe_stack_demo.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | using namespace std; 8 | 9 | mutex myMutex; 10 | 11 | class stack 12 | { 13 | public: 14 | stack() {}; 15 | ~stack() {}; 16 | void pop(); 17 | int top() { return data.back(); } 18 | void push(int); 19 | void print(); 20 | int getSize() { return data.size(); } 21 | private: 22 | vector data; 23 | }; 24 | 25 | void stack::pop() 26 | { 27 | lock_guard guard(myMutex); 28 | data.erase(data.end() - 1); 29 | } 30 | 31 | void stack::push(int n) 32 | { 33 | lock_guard guard(myMutex); 34 | data.push_back(n); 35 | } 36 | 37 | void stack::print() 38 | { 39 | cout << "initial stack : "; 40 | for (int item : data) 41 | cout << item << " "; 42 | cout << endl; 43 | } 44 | 45 | void process(int val, string s) 46 | { 47 | lock_guard guard(myMutex); 48 | cout << s << " : " << val << endl; 49 | } 50 | 51 | void thread_function(stack& st, string s) 52 | { 53 | int val = st.top(); 54 | st.pop(); 55 | process(val, s); 56 | } 57 | 58 | int main() 59 | { 60 | stack st; 61 | for (int i = 0; i < 10; i++) st.push(i); 62 | 63 | st.print(); 64 | 65 | while (true) { 66 | if (st.getSize() > 0) { 67 | thread t1(&thread_function, ref(st), string("thread1")); 68 | t1.join(); 69 | } 70 | else 71 | break; 72 | if (st.getSize() > 0) { 73 | thread t2(&thread_function, ref(st), string("thread2")); 74 | t2.join(); 75 | } 76 | else 77 | break; 78 | } 79 | 80 | return 0; 81 | } -------------------------------------------------------------------------------- /02.C++11/并发编程/02.线程同步/src/49.thread_cond_var.cpp: -------------------------------------------------------------------------------- 1 | #include // std::cout 2 | #include // std::thread 3 | #include // std::mutex, std::unique_lock 4 | #include // std::condition_variable 5 | 6 | std::mutex mtx; // 全局相互排斥锁. 7 | std::condition_variable cv; // 全局条件变量. 8 | bool ready = false; // 全局标志位. 9 | 10 | void do_print_id(int id) 11 | { 12 | std::unique_lock lck(mtx); 13 | while (!ready) // 假设标志位不为 true, 则等待... 14 | cv.wait(lck); // 当前线程被堵塞, 当全局标志位变为 true 之后, 15 | // 线程被唤醒, 继续往下运行打印线程编号id. 16 | std::cout << "thread " << id << '\n'; 17 | } 18 | 19 | void go() 20 | { 21 | std::unique_lock lck(mtx); 22 | ready = true; // 设置全局标志位为 true. 23 | cv.notify_all(); // 唤醒全部线程. 24 | } 25 | 26 | int main() 27 | { 28 | std::thread threads[10]; 29 | // spawn 10 threads: 30 | for (int i = 0; i < 10; ++i) 31 | threads[i] = std::thread(do_print_id, i); 32 | 33 | std::cout << "10 threads ready to race...\n"; 34 | go(); // go! 35 | 36 | for (auto & th : threads) 37 | th.join(); 38 | 39 | return 0; 40 | } -------------------------------------------------------------------------------- /02.C++11/并发编程/02.线程同步/src/50.thread_cond_wait.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hujiese/cpp-study/c94ec4adf61a059e7e768cabc2bcb7b276327bd6/02.C++11/并发编程/02.线程同步/src/50.thread_cond_wait.cpp -------------------------------------------------------------------------------- /02.C++11/并发编程/02.线程同步/src/51.thread_cond_waitfor.cpp: -------------------------------------------------------------------------------- 1 | #include // std::cout 2 | #include // std::thread 3 | #include // std::chrono::seconds 4 | #include // std::mutex, std::unique_lock 5 | #include // std::condition_variable, std::cv_status 6 | 7 | std::condition_variable cv; 8 | 9 | int value; 10 | 11 | void do_read_value() 12 | { 13 | std::cin >> value; 14 | cv.notify_one(); 15 | } 16 | 17 | int main() 18 | { 19 | std::cout << "Please, enter an integer (I'll be printing dots): \n"; 20 | std::thread th(do_read_value); 21 | 22 | std::mutex mtx; 23 | std::unique_lock lck(mtx); 24 | while (cv.wait_for(lck, std::chrono::seconds(1)) == std::cv_status::timeout) { 25 | std::cout << '.'; 26 | std::cout.flush(); 27 | } 28 | 29 | std::cout << "You entered: " << value << '\n'; 30 | 31 | th.join(); 32 | return 0; 33 | } -------------------------------------------------------------------------------- /02.C++11/并发编程/02.线程同步/src/52.thread_cond_notify_one.cpp: -------------------------------------------------------------------------------- 1 | #include // std::cout 2 | #include // std::thread 3 | #include // std::mutex, std::unique_lock 4 | #include // std::condition_variable 5 | 6 | std::mutex mtx; 7 | std::condition_variable cv; 8 | 9 | int cargo = 0; // shared value by producers and consumers 10 | 11 | void consumer() 12 | { 13 | std::unique_lock < std::mutex > lck(mtx); 14 | while (cargo == 0) 15 | cv.wait(lck); 16 | std::cout << cargo << '\n'; 17 | cargo = 0; 18 | } 19 | 20 | void producer(int id) 21 | { 22 | std::unique_lock < std::mutex > lck(mtx); 23 | cargo = id; 24 | cv.notify_one(); 25 | } 26 | 27 | int main() 28 | { 29 | std::thread consumers[10], producers[10]; 30 | 31 | // spawn 10 consumers and 10 producers: 32 | for (int i = 0; i < 10; ++i) { 33 | consumers[i] = std::thread(consumer); 34 | producers[i] = std::thread(producer, i + 1); 35 | } 36 | 37 | // join them back: 38 | for (int i = 0; i < 10; ++i) { 39 | producers[i].join(); 40 | consumers[i].join(); 41 | } 42 | 43 | return 0; 44 | } -------------------------------------------------------------------------------- /02.C++11/并发编程/02.线程同步/src/53.thread_cond_notify_all.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hujiese/cpp-study/c94ec4adf61a059e7e768cabc2bcb7b276327bd6/02.C++11/并发编程/02.线程同步/src/53.thread_cond_notify_all.cpp -------------------------------------------------------------------------------- /02.C++11/并发编程/03.future/src/55.thread_promise.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hujiese/cpp-study/c94ec4adf61a059e7e768cabc2bcb7b276327bd6/02.C++11/并发编程/03.future/src/55.thread_promise.cpp -------------------------------------------------------------------------------- /02.C++11/并发编程/03.future/src/56.thread_promise_ctor.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hujiese/cpp-study/c94ec4adf61a059e7e768cabc2bcb7b276327bd6/02.C++11/并发编程/03.future/src/56.thread_promise_ctor.cpp -------------------------------------------------------------------------------- /02.C++11/并发编程/03.future/src/57.thread_promise_exception.cpp: -------------------------------------------------------------------------------- 1 | #include // std::cin, std::cout, std::ios 2 | #include // std::ref 3 | #include // std::thread 4 | #include // std::promise, std::future 5 | #include // std::exception, std::current_exception 6 | 7 | void get_int(std::promise& prom) { 8 | int x; 9 | std::cout << "Please, enter an integer value: "; 10 | std::cin.exceptions(std::ios::failbit); // throw on failbit 11 | try { 12 | std::cin >> x; // sets failbit if input is not int 13 | prom.set_value(x); 14 | } 15 | catch (std::exception&) { 16 | prom.set_exception(std::current_exception()); 17 | } 18 | } 19 | 20 | void print_int(std::future& fut) { 21 | try { 22 | int x = fut.get(); 23 | std::cout << "value: " << x << '\n'; 24 | } 25 | catch (std::exception& e) { 26 | std::cout << "[exception caught: " << e.what() << "]\n"; 27 | } 28 | } 29 | 30 | int main() 31 | { 32 | std::promise prom; 33 | std::future fut = prom.get_future(); 34 | 35 | std::thread th1(get_int, std::ref(prom)); 36 | std::thread th2(print_int, std::ref(fut)); 37 | 38 | th1.join(); 39 | th2.join(); 40 | return 0; 41 | } -------------------------------------------------------------------------------- /02.C++11/并发编程/03.future/src/58.thread_packaged_task.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hujiese/cpp-study/c94ec4adf61a059e7e768cabc2bcb7b276327bd6/02.C++11/并发编程/03.future/src/58.thread_packaged_task.cpp -------------------------------------------------------------------------------- /02.C++11/并发编程/03.future/src/59.thread_packaged_task_ctor.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hujiese/cpp-study/c94ec4adf61a059e7e768cabc2bcb7b276327bd6/02.C++11/并发编程/03.future/src/59.thread_packaged_task_ctor.cpp -------------------------------------------------------------------------------- /02.C++11/并发编程/03.future/src/60.thread_packaged_task_valid.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hujiese/cpp-study/c94ec4adf61a059e7e768cabc2bcb7b276327bd6/02.C++11/并发编程/03.future/src/60.thread_packaged_task_valid.cpp -------------------------------------------------------------------------------- /02.C++11/并发编程/03.future/src/61.thread_packaged_task_reset.cpp: -------------------------------------------------------------------------------- 1 | #include // std::cout 2 | #include // std::move 3 | #include // std::packaged_task, std::future 4 | #include // std::thread 5 | 6 | // a simple task: 7 | int triple(int x) { return x * 3; } 8 | 9 | int main() 10 | { 11 | std::packaged_task tsk(triple); // package task 12 | 13 | 14 | std::future fut = tsk.get_future(); 15 | std::thread(std::move(tsk), 100).detach(); 16 | std::cout << "The triple of 100 is " << fut.get() << ".\n"; 17 | 18 | 19 | // re-use same task object: 20 | tsk.reset(); 21 | fut = tsk.get_future(); 22 | std::thread(std::move(tsk), 200).detach(); 23 | std::cout << "Thre triple of 200 is " << fut.get() << ".\n"; 24 | 25 | return 0; 26 | } -------------------------------------------------------------------------------- /02.C++11/并发编程/03.future/src/62.thread_future.cpp: -------------------------------------------------------------------------------- 1 | // future example 2 | #include // std::cout 3 | #include // std::async, std::future 4 | #include // std::chrono::milliseconds 5 | 6 | // a non-optimized way of checking for prime numbers: 7 | bool is_prime(int x) 8 | { 9 | for (int i = 2; i < x; ++i) 10 | if (x % i == 0) 11 | return false; 12 | return true; 13 | } 14 | 15 | int main() 16 | { 17 | // call function asynchronously: 18 | std::future < bool > fut = std::async(is_prime, 444444443); 19 | 20 | // do something while waiting for function to set future: 21 | std::cout << "checking, please wait"; 22 | std::chrono::milliseconds span(100); 23 | while (fut.wait_for(span) == std::future_status::timeout) 24 | std::cout << '.'; 25 | 26 | bool x = fut.get(); // retrieve return value 27 | 28 | std::cout << "\n444444443 " << (x ? "is" : "is not") << " prime.\n"; 29 | 30 | return 0; 31 | } -------------------------------------------------------------------------------- /02.C++11/并发编程/03.future/src/63.thread_future_shared.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hujiese/cpp-study/c94ec4adf61a059e7e768cabc2bcb7b276327bd6/02.C++11/并发编程/03.future/src/63.thread_future_shared.cpp -------------------------------------------------------------------------------- /02.C++11/并发编程/03.future/src/64.thread_future_get.cpp: -------------------------------------------------------------------------------- 1 | #include // std::cin, std::cout, std::ios 2 | #include // std::ref 3 | #include // std::thread 4 | #include // std::promise, std::future 5 | #include // std::exception, std::current_exception 6 | 7 | void get_int(std::promise& prom) { 8 | int x; 9 | std::cout << "Please, enter an integer value: "; 10 | std::cin.exceptions(std::ios::failbit); // throw on failbit 11 | try { 12 | std::cin >> x; // sets failbit if input is not int 13 | prom.set_value(x); 14 | } 15 | catch (std::exception&) { 16 | prom.set_exception(std::current_exception()); 17 | } 18 | } 19 | 20 | void print_int(std::future& fut) { 21 | try { 22 | int x = fut.get(); 23 | std::cout << "value: " << x << '\n'; 24 | } 25 | catch (std::exception& e) { 26 | std::cout << "[exception caught: " << e.what() << "]\n"; 27 | } 28 | } 29 | 30 | int main() 31 | { 32 | std::promise prom; 33 | std::future fut = prom.get_future(); 34 | 35 | std::thread th1(get_int, std::ref(prom)); 36 | std::thread th2(print_int, std::ref(fut)); 37 | 38 | th1.join(); 39 | th2.join(); 40 | return 0; 41 | } -------------------------------------------------------------------------------- /02.C++11/并发编程/03.future/src/65.thread_future_valid.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hujiese/cpp-study/c94ec4adf61a059e7e768cabc2bcb7b276327bd6/02.C++11/并发编程/03.future/src/65.thread_future_valid.cpp -------------------------------------------------------------------------------- /02.C++11/并发编程/03.future/src/66.thread_future_wait.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hujiese/cpp-study/c94ec4adf61a059e7e768cabc2bcb7b276327bd6/02.C++11/并发编程/03.future/src/66.thread_future_wait.cpp -------------------------------------------------------------------------------- /02.C++11/并发编程/03.future/src/67.thread_future_wait_for.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hujiese/cpp-study/c94ec4adf61a059e7e768cabc2bcb7b276327bd6/02.C++11/并发编程/03.future/src/67.thread_future_wait_for.cpp -------------------------------------------------------------------------------- /02.C++11/并发编程/03.future/src/68.thread_future_async.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | double ThreadTask(int n) { 10 | std::cout << std::this_thread::get_id() 11 | << " start computing..." << std::endl; 12 | 13 | double ret = 0; 14 | for (int i = 0; i <= n; i++) { 15 | ret += std::sin(i); 16 | } 17 | 18 | std::cout << std::this_thread::get_id() 19 | << " finished computing..." << std::endl; 20 | return ret; 21 | } 22 | 23 | int main(int argc, const char *argv[]) 24 | { 25 | std::future f(std::async(std::launch::async, ThreadTask, 100000000)); 26 | 27 | #if 0 28 | while (f.wait_until(std::chrono::system_clock::now() + std::chrono::seconds(1)) 29 | != std::future_status::ready) { 30 | std::cout << "task is running...\n"; 31 | } 32 | #else 33 | while (f.wait_for(std::chrono::seconds(1)) 34 | != std::future_status::ready) { 35 | std::cout << "task is running...\n"; 36 | } 37 | #endif 38 | 39 | std::cout << f.get() << std::endl; 40 | 41 | return EXIT_SUCCESS; 42 | } -------------------------------------------------------------------------------- /02.C++11/并发编程/03.future/src/69.thread_future_launch.cpp: -------------------------------------------------------------------------------- 1 | #include // std::cout 2 | #include // std::async, std::future, std::launch 3 | #include // std::chrono::milliseconds 4 | #include // std::this_thread::sleep_for 5 | 6 | void do_print_ten(char c, int ms) 7 | { 8 | for (int i = 0; i < 10; ++i) { 9 | std::this_thread::sleep_for(std::chrono::milliseconds(ms)); 10 | std::cout << c; 11 | } 12 | } 13 | 14 | int main() 15 | { 16 | std::cout << "with launch::async:\n"; 17 | std::future < void >foo = std::async(std::launch::async, do_print_ten, '*', 100); 18 | std::future < void >bar = std::async(std::launch::async, do_print_ten, '@', 200); 19 | // async "get" (wait for foo and bar to be ready): 20 | foo.get(); 21 | bar.get(); 22 | std::cout << "\n\n"; 23 | 24 | std::cout << "with launch::deferred:\n"; 25 | foo = std::async(std::launch::deferred, do_print_ten, '*', 100); 26 | bar = std::async(std::launch::deferred, do_print_ten, '@', 200); 27 | // deferred "get" (perform the actual calls): 28 | foo.get(); 29 | bar.get(); 30 | std::cout << '\n'; 31 | 32 | return 0; 33 | } -------------------------------------------------------------------------------- /02.C++11/并发编程/04.线程池/README.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | - [线程池--C++11仿muduo](#%E7%BA%BF%E7%A8%8B%E6%B1%A0--c11%E4%BB%BFmuduo) 6 | - [线程池--复杂版](#%E7%BA%BF%E7%A8%8B%E6%B1%A0--%E5%A4%8D%E6%9D%82%E7%89%88) 7 | - [1、std::result_of](#1stdresult_of) 8 | - [2、C++函数包装器](#2c%E5%87%BD%E6%95%B0%E5%8C%85%E8%A3%85%E5%99%A8) 9 | - [3、std::future](#3stdfuture) 10 | - [4、线程池实现](#4%E7%BA%BF%E7%A8%8B%E6%B1%A0%E5%AE%9E%E7%8E%B0) 11 | 12 | 13 | ## 线程池--C++11仿muduo 14 | 15 | 见 src/mythread 16 | 17 | ## 线程池--复杂版 18 | 19 | 参考 [C++11的简单线程池代码阅读](https://www.cnblogs.com/oloroso/p/5881863.html) 20 | 21 | 原理就是管理一个任务队列和一个工作线程队列。 22 | 23 | 工作线程不断的从任务队列取任务,然后执行。如果没有任务就等待新任务的到来。添加新任务的时候先添加到任务队列,然后通知任意(条件变量notify_one)一个线程有新的任务来了。 24 | 25 | ### 1、std::result_of 26 | 27 | std::result_of可以在编译的时候推导出一个函数表达式的返回值类型: 28 | 29 | ```c 30 | #include 31 | 32 | struct S { 33 | double operator()(char, int&); // 这个函数的返回类型是 double 34 | }; 35 | 36 | int main() 37 | { 38 | 39 | std::result_of::type foo = 3.14; // 使用这样的写法会推导出模板参数中函数的返回值类型 40 | typedef std::result_of::type MyType; // 是 double 类型吗? 41 | std::cout << "foo's type is double: " << std::is_same::value << std::endl; // foo's type is double: 1 42 | return 0; 43 | } 44 | ``` 45 | 46 | ### 2、C++函数包装器 47 | 该部分参考 [C++函数包装器](https://blog.csdn.net/huangshanchun/article/details/45647911) 48 | 49 | 函数包装器把函数包装起来:有以下特点 50 | * 设计通用的函数执行接口,可以设置计数(函数执行次数)和关卡 51 | * 函数包装器依赖于函数模板,实现通用泛型 52 | * 函数代码可以内嵌在函数中 53 | * 原理是函数指针实现的 54 | 55 | 以下给出C++简单的函数包装器案例: 56 | 57 | ```c 58 | #include 59 | #include 60 | using namespace std; 61 | 62 | //定义好了一个函数包装器 63 | template < typename F, typename T> 64 | T function_wrapper(F fun, T t) 65 | { 66 | return fun(t); 67 | } 68 | //定义好了一个函数包装器 69 | template < typename F, typename T> 70 | T function_wrapper(F fun, T t1, T t2) 71 | { 72 | static int count = 0; 73 | count++; 74 | cout << "函数包装器执行" << count << "次数" << endl; 75 | 76 | return fun(t1, t2); 77 | } 78 | int main() 79 | { 80 | double d_num = 1.1; 81 | //double(double)是声明函数类型 82 | //允许函数内嵌 83 | //本质是函数指针 84 | // [] 标识要开辟一个函数 85 | function square_fun = [](double in_data) 86 | { 87 | return in_data*in_data; 88 | }; 89 | function cube_fun = [](double in_data) 90 | { 91 | return in_data*in_data*in_data; 92 | }; 93 | function add_fun = [](int in_data1, int in_data2) 94 | { 95 | return in_data1 + in_data2; 96 | }; 97 | cout << function_wrapper(square_fun, d_num) << " " << function_wrapper(cube_fun, d_num) << endl; 98 | cout << function_wrapper(add_fun, 1, 2) << endl; 99 | 100 | return 0; 101 | } 102 | ``` 103 | ### 3、std::future 104 | 105 | 详见相关章节。 106 | 107 | ### 4、线程池实现 108 | 109 | 见附录代码,代码中有大量注解。 -------------------------------------------------------------------------------- /02.C++11/并发编程/04.线程池/src/54.thread_pool_demo.cpp: -------------------------------------------------------------------------------- 1 | //#include 2 | //#include 3 | //#include 4 | // 5 | //#include "ThreadPool.h" 6 | // 7 | //int main() 8 | //{ 9 | // 10 | // ThreadPool pool(4); 11 | // std::vector< std::future > results; 12 | // 13 | // for (int i = 0; i < 8; ++i) { 14 | // results.emplace_back( 15 | // pool.enqueue([i] { 16 | // std::cout << "hello " << i << std::endl; 17 | // std::this_thread::sleep_for(std::chrono::seconds(1)); 18 | // std::cout << "world " << i << std::endl; 19 | // return i*i; 20 | // }) 21 | // ); 22 | // } 23 | // 24 | // for (auto && result : results) 25 | // std::cout << result.get() << ' '; 26 | // std::cout << std::endl; 27 | // 28 | // return 0; 29 | //} -------------------------------------------------------------------------------- /02.C++11/并发编程/04.线程池/src/70.result_of.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hujiese/cpp-study/c94ec4adf61a059e7e768cabc2bcb7b276327bd6/02.C++11/并发编程/04.线程池/src/70.result_of.cpp -------------------------------------------------------------------------------- /02.C++11/并发编程/04.线程池/src/71.func_package.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hujiese/cpp-study/c94ec4adf61a059e7e768cabc2bcb7b276327bd6/02.C++11/并发编程/04.线程池/src/71.func_package.cpp -------------------------------------------------------------------------------- /02.C++11/并发编程/04.线程池/src/ThreadPool.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hujiese/cpp-study/c94ec4adf61a059e7e768cabc2bcb7b276327bd6/02.C++11/并发编程/04.线程池/src/ThreadPool.h -------------------------------------------------------------------------------- /02.C++11/并发编程/04.线程池/src/mythread/MyThreadPool.cpp: -------------------------------------------------------------------------------- 1 | #include "MyThreadPool.h" 2 | #include 3 | #include 4 | #include 5 | using namespace hujie; 6 | 7 | ThreadPool::ThreadPool(const std::string& name) 8 | :name_(name), 9 | running_(false) 10 | { 11 | } 12 | 13 | ThreadPool::~ThreadPool() 14 | { 15 | if (running_) 16 | { 17 | stop(); 18 | } 19 | } 20 | 21 | void ThreadPool::start(int numThreads) 22 | { 23 | assert(threads_.empty()); 24 | running_ = true; 25 | threads_.reserve(numThreads); 26 | for (int i = 0; i < numThreads; ++i) 27 | { 28 | char id[32]; 29 | _snprintf_s(id, sizeof id, "%d", i); 30 | threads_.push_back(std::thread(std::bind(&ThreadPool::runInThread, this), name_ + id)); 31 | } 32 | } 33 | 34 | void ThreadPool::stop() 35 | { 36 | { 37 | std::unique_lock lock(mutex_); 38 | running_ = false; 39 | cond_.notify_all(); 40 | } 41 | std::for_each(threads_.begin(), threads_.end(), std::bind(&std::thread::join, std::placeholders::_1)); 42 | } 43 | 44 | void ThreadPool::run(const Task& task) 45 | { 46 | if (threads_.empty()) 47 | { 48 | task(); 49 | } 50 | else 51 | { 52 | std::unique_lock lock(mutex_); 53 | queue_.push_back(task); 54 | cond_.notify_all(); 55 | } 56 | } 57 | 58 | ThreadPool::Task ThreadPool::take() 59 | { 60 | std::unique_lock lock(mutex_); 61 | // always use a while-loop, due to spurious wakeup 62 | while (queue_.empty() && running_) 63 | { 64 | cond_.wait(lock); 65 | } 66 | Task task; 67 | if (!queue_.empty()) 68 | { 69 | task = queue_.front(); 70 | queue_.pop_front(); 71 | } 72 | return task; 73 | } 74 | 75 | void ThreadPool::runInThread() 76 | { 77 | try 78 | { 79 | while (running_) 80 | { 81 | Task task(take()); 82 | if (task) 83 | { 84 | task(); 85 | } 86 | } 87 | } 88 | catch (const std::exception& ex) 89 | { 90 | fprintf(stderr, "exception caught in ThreadPool %s\n", name_.c_str()); 91 | fprintf(stderr, "reason: %s\n", ex.what()); 92 | abort(); 93 | } 94 | catch (...) 95 | { 96 | fprintf(stderr, "unknown exception caught in ThreadPool %s\n", name_.c_str()); 97 | throw; // rethrow 98 | } 99 | } 100 | 101 | -------------------------------------------------------------------------------- /02.C++11/并发编程/04.线程池/src/mythread/MyThreadPool.h: -------------------------------------------------------------------------------- 1 | #ifndef __THREADPOOL_H 2 | #define __THREADPOOL_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | namespace hujie 13 | { 14 | 15 | class ThreadPool 16 | { 17 | public: 18 | typedef std::function Task; 19 | 20 | explicit ThreadPool(const std::string& name = std::string()); 21 | ~ThreadPool(); 22 | 23 | void start(int numThreads); 24 | void stop(); 25 | 26 | void run(const Task& f); 27 | 28 | private: 29 | void runInThread(); 30 | Task take(); 31 | 32 | std::mutex mutex_; 33 | std::condition_variable cond_; 34 | std::string name_; 35 | std::vector threads_; 36 | std::deque queue_; 37 | bool running_; 38 | }; 39 | } 40 | #endif // !__THREADPOOL_H 41 | -------------------------------------------------------------------------------- /02.C++11/并发编程/04.线程池/src/mythread/testMyThredPool.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "MyThreadPool.h" 3 | using namespace std; 4 | 5 | void print() 6 | { 7 | printf("tid=%d\n", std::this_thread::get_id()); 8 | } 9 | 10 | void printString(const std::string& str) 11 | { 12 | /*printf("tid=%d, str=%s\n", std::this_thread::get_id(), str.c_str());*/ 13 | printf("tid=%d\t", std::this_thread::get_id()); 14 | printf("str=%s\n", str.c_str()); 15 | 16 | } 17 | 18 | int main() 19 | { 20 | hujie::ThreadPool pool("MainThreadPool"); 21 | pool.start(5); 22 | 23 | pool.run(print); 24 | for (int i = 0; i < 100; ++i) 25 | { 26 | char buf[32]; 27 | _snprintf_s(buf, sizeof buf, "task %d", i); 28 | pool.run(std::bind(printString, std::string(buf))); 29 | } 30 | //pool.stop(); 31 | while (true); 32 | } -------------------------------------------------------------------------------- /02.C++11/智能指针/img/circle_reference.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hujiese/cpp-study/c94ec4adf61a059e7e768cabc2bcb7b276327bd6/02.C++11/智能指针/img/circle_reference.png -------------------------------------------------------------------------------- /02.C++11/智能指针/src/25.shared_ptr.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hujiese/cpp-study/c94ec4adf61a059e7e768cabc2bcb7b276327bd6/02.C++11/智能指针/src/25.shared_ptr.cpp -------------------------------------------------------------------------------- /02.C++11/智能指针/src/26.shared_ptr2.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | class Test 4 | { 5 | public: 6 | Test() 7 | { 8 | std::cout << "Test()" << std::endl; 9 | } 10 | void print(void) 11 | { 12 | std::cout << "----------Test::print(void)----------" << std::endl; 13 | } 14 | ~Test() 15 | { 16 | std::cout << "~Test()" << std::endl; 17 | } 18 | }; 19 | int main() 20 | { 21 | std::shared_ptr p1 = std::make_shared(); 22 | std::cout << "1 ref:" << p1.use_count() << std::endl; 23 | { 24 | std::shared_ptr p2 = p1; 25 | std::cout << "2 ref:" << p1.use_count() << std::endl; 26 | } 27 | std::cout << "3 ref:" << p1.use_count() << std::endl; 28 | 29 | std::cout << "--------------------------" << std::endl; 30 | 31 | std::shared_ptr temp(new Test()); 32 | temp->print(); 33 | 34 | Test* temp2 = temp.get(); 35 | temp2->print(); 36 | 37 | return 0; 38 | } -------------------------------------------------------------------------------- /02.C++11/智能指针/src/27.unique_ptr.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hujiese/cpp-study/c94ec4adf61a059e7e768cabc2bcb7b276327bd6/02.C++11/智能指针/src/27.unique_ptr.cpp -------------------------------------------------------------------------------- /02.C++11/智能指针/src/28.weak_ptr.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int main() { 5 | { 6 | std::shared_ptr sh_ptr = std::make_shared(10); 7 | std::cout << sh_ptr.use_count() << std::endl; // 1 8 | 9 | std::weak_ptr wp(sh_ptr); 10 | std::cout << wp.use_count() << std::endl; // 1 11 | 12 | if (!wp.expired()){ 13 | std::shared_ptr sh_ptr2 = wp.lock(); //get another shared_ptr 14 | *sh_ptr = 100; 15 | std::cout << wp.use_count() << std::endl; // 2 16 | } 17 | } 18 | //release memory 19 | } -------------------------------------------------------------------------------- /02.C++11/智能指针/src/29.circle_reference.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | class Child; 5 | class Parent; 6 | 7 | class Parent 8 | { 9 | private: 10 | Child* myChild; 11 | public: 12 | void setChild(Child* ch) 13 | { 14 | this->myChild = ch; 15 | } 16 | 17 | void doSomething() 18 | { 19 | if (this->myChild) 20 | { 21 | 22 | } 23 | } 24 | 25 | ~Parent() 26 | { 27 | delete myChild; 28 | std::cout << "Parent's dtor" << std::endl; 29 | } 30 | }; 31 | 32 | class Child 33 | { 34 | private: 35 | Parent* myParent; 36 | public: 37 | void setPartent(Parent* p) 38 | { 39 | this->myParent = p; 40 | } 41 | void doSomething() 42 | { 43 | if (this->myParent) 44 | { 45 | 46 | } 47 | } 48 | ~Child() 49 | { 50 | delete myParent; 51 | std::cout << "Child's dtor" << std::endl; 52 | } 53 | }; 54 | 55 | int main() 56 | { 57 | { 58 | Parent* p = new Parent; 59 | Child* c = new Child; 60 | p->setChild(c); 61 | c->setPartent(p); 62 | delete c; //only delete one 63 | } 64 | return 0; 65 | } -------------------------------------------------------------------------------- /02.C++11/智能指针/src/30.circle_reference2.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | class Child; 5 | class Parent; 6 | 7 | class Parent { 8 | private: 9 | std::shared_ptr ChildPtr; 10 | public: 11 | void setChild(std::shared_ptr child) { 12 | this->ChildPtr = child; 13 | } 14 | 15 | void doSomething() { 16 | if (this->ChildPtr.use_count()) { 17 | 18 | } 19 | } 20 | 21 | ~Parent() { 22 | std::cout << "Parent's dtor" << std::endl; 23 | } 24 | }; 25 | 26 | class Child { 27 | private: 28 | std::shared_ptr ParentPtr; 29 | public: 30 | void setPartent(std::shared_ptr parent) { 31 | this->ParentPtr = parent; 32 | } 33 | void doSomething() { 34 | if (this->ParentPtr.use_count()) { 35 | 36 | } 37 | } 38 | ~Child() { 39 | std::cout << "Child's dtor" << std::endl; 40 | } 41 | }; 42 | 43 | int main() { 44 | std::weak_ptr wpp; 45 | std::weak_ptr wpc; 46 | { 47 | std::shared_ptr p(new Parent); 48 | std::shared_ptr c(new Child); 49 | p->setChild(c); 50 | c->setPartent(p); 51 | wpp = p; 52 | wpc = c; 53 | std::cout << p.use_count() << std::endl; // 2 54 | std::cout << c.use_count() << std::endl; // 2 55 | } 56 | std::cout << wpp.use_count() << std::endl; // 1 57 | std::cout << wpc.use_count() << std::endl; // 1 58 | return 0; 59 | } -------------------------------------------------------------------------------- /02.C++11/智能指针/src/31.circle_reference_solve.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | class Child; 5 | class Parent; 6 | 7 | class Parent { 8 | private: 9 | //std::shared_ptr ChildPtr; 10 | std::weak_ptr ChildPtr; 11 | public: 12 | void setChild(std::shared_ptr child) { 13 | this->ChildPtr = child; 14 | } 15 | 16 | void doSomething() { 17 | //new shared_ptr 18 | if (this->ChildPtr.lock()) { 19 | 20 | } 21 | } 22 | 23 | ~Parent() { 24 | std::cout << "Parent's dtor" << std::endl; 25 | } 26 | }; 27 | 28 | class Child { 29 | private: 30 | std::shared_ptr ParentPtr; 31 | public: 32 | void setPartent(std::shared_ptr parent) { 33 | this->ParentPtr = parent; 34 | } 35 | void doSomething() { 36 | if (this->ParentPtr.use_count()) { 37 | 38 | } 39 | } 40 | ~Child() { 41 | std::cout << "Child's dtor" << std::endl; 42 | } 43 | }; 44 | 45 | int main() { 46 | std::weak_ptr wpp; 47 | std::weak_ptr wpc; 48 | { 49 | std::shared_ptr p(new Parent); 50 | std::shared_ptr c(new Child); 51 | p->setChild(c); 52 | c->setPartent(p); 53 | wpp = p; 54 | wpc = c; 55 | std::cout << p.use_count() << std::endl; // 2 56 | std::cout << c.use_count() << std::endl; // 1 57 | } 58 | std::cout << wpp.use_count() << std::endl; // 0 59 | std::cout << wpc.use_count() << std::endl; // 0 60 | return 0; 61 | } -------------------------------------------------------------------------------- /02.C++11/智能指针/src/32.realize_smart_ptr.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | //#include 3 | 4 | template 5 | class SmartPointer { 6 | private: 7 | T* _ptr; 8 | size_t* _count; 9 | public: 10 | SmartPointer(T* ptr = nullptr) : 11 | _ptr(ptr) { 12 | if (_ptr) { 13 | _count = new size_t(1); 14 | } 15 | else { 16 | _count = new size_t(0); 17 | } 18 | } 19 | 20 | SmartPointer(const SmartPointer& ptr) { 21 | this->_ptr = ptr._ptr; 22 | this->_count = ptr._count; 23 | (*this->_count)++; 24 | } 25 | 26 | SmartPointer& operator=(const SmartPointer& ptr) { 27 | if (this->_ptr == ptr._ptr) { 28 | return *this; 29 | } 30 | 31 | if (this->_ptr) { 32 | (*this->_count)--; 33 | if (this->_count == 0) { 34 | delete this->_ptr; 35 | delete this->_count; 36 | } 37 | } 38 | 39 | this->_ptr = ptr._ptr; 40 | this->_count = ptr._count; 41 | (*this->_count)++; 42 | return *this; 43 | } 44 | 45 | T& operator*() { 46 | assert(this->_ptr == nullptr); 47 | return *(this->_ptr); 48 | 49 | } 50 | 51 | T* operator->() { 52 | assert(this->_ptr == nullptr); 53 | return this->_ptr; 54 | } 55 | 56 | ~SmartPointer() { 57 | (*this->_count)--; 58 | if (*this->_count == 0) { 59 | delete this->_ptr; 60 | delete this->_count; 61 | } 62 | } 63 | 64 | size_t use_count(){ 65 | return *this->_count; 66 | } 67 | }; 68 | 69 | int main() { 70 | { 71 | SmartPointer sp(new int(10)); 72 | std::cout << sp.use_count() << std::endl; // 1 73 | 74 | 75 | { 76 | SmartPointer sp2(sp); 77 | std::cout << sp.use_count() << std::endl; // 2 78 | std::cout << sp2.use_count() << std::endl; // 2 79 | 80 | SmartPointer sp3(new int(20)); 81 | std::cout << sp3.use_count() << std::endl; // 1 82 | 83 | //sp2 = sp3; 84 | std::cout << sp.use_count() << std::endl;// 2 85 | std::cout << sp2.use_count() << std::endl; // 2 86 | std::cout << sp3.use_count() << std::endl;// 1 87 | } 88 | 89 | std::cout << sp.use_count() << std::endl;// 1 90 | } 91 | //delete operator 92 | } -------------------------------------------------------------------------------- /03.STL/01.STL使用/algorithm/img/algorithm.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hujiese/cpp-study/c94ec4adf61a059e7e768cabc2bcb7b276327bd6/03.STL/01.STL使用/algorithm/img/algorithm.png -------------------------------------------------------------------------------- /03.STL/01.STL使用/algorithm/src/87.stl_algorithm_one_func_obj.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hujiese/cpp-study/c94ec4adf61a059e7e768cabc2bcb7b276327bd6/03.STL/01.STL使用/algorithm/src/87.stl_algorithm_one_func_obj.cpp -------------------------------------------------------------------------------- /03.STL/01.STL使用/algorithm/src/88.stl_algorithm_one_pred.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hujiese/cpp-study/c94ec4adf61a059e7e768cabc2bcb7b276327bd6/03.STL/01.STL使用/algorithm/src/88.stl_algorithm_one_pred.cpp -------------------------------------------------------------------------------- /03.STL/01.STL使用/algorithm/src/89.stl_algorithm_two_func_obj.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | using namespace std; 7 | 8 | template 9 | struct SumAdd 10 | { 11 | T operator()(T &t1, T &t2) 12 | { 13 | return t1 + t2; 14 | } 15 | }; 16 | 17 | template 18 | void printE(T &t) 19 | { 20 | for (vector::iterator it = t.begin(); it != t.end(); it++) 21 | { 22 | cout << *it << " "; 23 | } 24 | } 25 | 26 | void printVector(vector &v) 27 | { 28 | for (vector::iterator it = v.begin(); it != v.end(); it++) 29 | { 30 | cout << *it << " "; 31 | } 32 | } 33 | 34 | void main() 35 | { 36 | vector v1, v2; 37 | vector v3; 38 | v1.push_back(1); 39 | v1.push_back(2); 40 | v1.push_back(3); 41 | 42 | v2.push_back(4); 43 | v2.push_back(5); 44 | v2.push_back(6); 45 | 46 | v3.resize(10); 47 | 48 | //transform(v1.begin(), v1.end(), v2.begin(),v3.begin(), SumAdd()); 49 | /* 50 | template inline 54 | _OutIt transform(_InIt1 _First1, _InIt1 _Last1, 55 | _InIt2 _First2, _OutIt _Dest, _Fn2 _Func) 56 | */ 57 | vector::iterator it = transform(v1.begin(), v1.end(), v2.begin(), v3.begin(), SumAdd()); 58 | cout << *it << endl; 59 | printE(v3); 60 | } 61 | -------------------------------------------------------------------------------- /03.STL/01.STL使用/algorithm/src/90.stl_algorithm_two_pred.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | using namespace std; 7 | 8 | void current(int &v) 9 | { 10 | cout << v << " "; 11 | } 12 | 13 | bool MyCompare(const int &a, const int &b) 14 | { 15 | return a < b; 16 | } 17 | void main() 18 | { 19 | vector v(10); 20 | 21 | for (int i = 0; i<10; i++) 22 | { 23 | v[i] = rand() % 100; 24 | } 25 | 26 | for_each(v.begin(), v.end(), current); 27 | printf("\n"); 28 | sort(v.begin(), v.end(), MyCompare); 29 | 30 | printf("\n"); 31 | for (int i = 0; i<10; i++) 32 | { 33 | printf("%d ", v[i]); 34 | } 35 | printf("\n"); 36 | } 37 | -------------------------------------------------------------------------------- /03.STL/01.STL使用/algorithm/src/91.stl_algorithm_std_func_obj.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hujiese/cpp-study/c94ec4adf61a059e7e768cabc2bcb7b276327bd6/03.STL/01.STL使用/algorithm/src/91.stl_algorithm_std_func_obj.cpp -------------------------------------------------------------------------------- /03.STL/01.STL使用/algorithm/src/92.stl_algorithm_std_relation_func_obj.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | using namespace std; 7 | 8 | void main() 9 | { 10 | vector v1; 11 | v1.push_back("bbb"); 12 | v1.push_back("aaa"); 13 | v1.push_back("ccc"); 14 | v1.push_back("zzzz"); 15 | v1.push_back("ccc"); 16 | string s1 = "ccc"; 17 | //int num = count_if(v1.begin(),v1.end(), equal_to(),s1); 18 | int num = count_if(v1.begin(), v1.end(), bind2nd(equal_to(), s1)); 19 | cout << num << endl; 20 | } 21 | -------------------------------------------------------------------------------- /03.STL/01.STL使用/algorithm/src/93.stl_algorithm_bind1st_2nd.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hujiese/cpp-study/c94ec4adf61a059e7e768cabc2bcb7b276327bd6/03.STL/01.STL使用/algorithm/src/93.stl_algorithm_bind1st_2nd.cpp -------------------------------------------------------------------------------- /03.STL/01.STL使用/algorithm/src/94.stl_algorithm_for_each.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hujiese/cpp-study/c94ec4adf61a059e7e768cabc2bcb7b276327bd6/03.STL/01.STL使用/algorithm/src/94.stl_algorithm_for_each.cpp -------------------------------------------------------------------------------- /03.STL/01.STL使用/algorithm/src/95.stl_algorithm_transform.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | using namespace std; 7 | 8 | int increase(int i) 9 | { 10 | return i + 1; 11 | } 12 | 13 | void main() 14 | { 15 | vector vecIntA; 16 | vecIntA.push_back(1); 17 | vecIntA.push_back(3); 18 | vecIntA.push_back(5); 19 | vecIntA.push_back(7); 20 | vecIntA.push_back(9); 21 | transform(vecIntA.begin(), vecIntA.end(), vecIntA.begin(), increase); //vecIntA : {2,4,6,8,10} 22 | transform(vecIntA.begin(), vecIntA.end(), vecIntA.begin(), negate()); 23 | } 24 | -------------------------------------------------------------------------------- /03.STL/01.STL使用/deque/README.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | - [STL -- deque](#stl----deque) 5 | - [1、介绍](#1%E4%BB%8B%E7%BB%8D) 6 | - [2、默认构造函数](#2%E9%BB%98%E8%AE%A4%E6%9E%84%E9%80%A0%E5%87%BD%E6%95%B0) 7 | - [3、添加移除操作](#3%E6%B7%BB%E5%8A%A0%E7%A7%BB%E9%99%A4%E6%93%8D%E4%BD%9C) 8 | - [4、deque的数据存取](#4deque%E7%9A%84%E6%95%B0%E6%8D%AE%E5%AD%98%E5%8F%96) 9 | - [5、deque与迭代器](#5deque%E4%B8%8E%E8%BF%AD%E4%BB%A3%E5%99%A8) 10 | - [6、deque的带参构造函数](#6deque%E7%9A%84%E5%B8%A6%E5%8F%82%E6%9E%84%E9%80%A0%E5%87%BD%E6%95%B0) 11 | - [7、deque的赋值](#7deque%E7%9A%84%E8%B5%8B%E5%80%BC) 12 | - [8、deque的大小](#8deque%E7%9A%84%E5%A4%A7%E5%B0%8F) 13 | - [9、deque插入元素](#9deque%E6%8F%92%E5%85%A5%E5%85%83%E7%B4%A0) 14 | - [10、deque删除元素](#10deque%E5%88%A0%E9%99%A4%E5%85%83%E7%B4%A0) 15 | - [11、使用案例](#11%E4%BD%BF%E7%94%A8%E6%A1%88%E4%BE%8B) 16 | 17 | 18 | 19 | ## STL -- deque 20 | 21 | ### 1、介绍 22 | 23 | * deque是“double-ended queue”的缩写,和vector一样都是STL的容器,deque是双端数组,而vector是单端的。 24 | * deque在接口上和vector非常相似,在许多操作的地方可以直接替换。 25 | * deque可以随机存取元素(支持索引值直接存取, 用[]操作符或at()方法,这个等下会详讲)。 26 | * deque头部和尾部添加或移除元素都非常快速。但是在中部安插元素或移除元素比较费时。 27 | 28 | ### 2、默认构造函数 29 | 30 | deque采用模板类实现,deque对象的默认构造形式: 31 | ```c 32 | deque deqT; // 尖括号内可以设置指针类型或自定义类型。 33 | deque deqInt; //一个存放int的deque容器。 34 | deque deqFloat; //一个存放float的deque容器。 35 | deque deqString; //一个存放string的deque容器。 36 | ``` 37 | 38 | ### 3、添加移除操作 39 | 40 | 操作函数: 41 | ```c 42 | deque.push_back(elem); //在容器尾部添加一个数据 43 | deque.push_front(elem); //在容器头部插入一个数据 44 | deque.pop_back(); //删除容器最后一个数据 45 | deque.pop_front(); //删除容器第一个数据 46 | ``` 47 | 48 | 使用方法如下: 49 | ```c 50 | deque deqInt; 51 | deqInt.push_back(1); 52 | deqInt.push_back(3); 53 | deqInt.push_back(5); 54 | deqInt.pop_front(); 55 | deqInt.pop_front(); 56 | deqInt.push_front(11); 57 | deqInt.push_front(13); 58 | deqInt.pop_back(); 59 | deqInt.pop_back(); 60 | //最终结果 deqInt { 13,11,5} 61 | ``` 62 | 63 | ### 4、deque的数据存取 64 | 65 | 可通过下面这些函数来获取相关元素: 66 | ```c 67 | deque.at(idx); //返回索引idx所指的数据,如果idx越界,抛出out_of_range。 68 | deque[idx]; //返回索引idx所指的数据,如果idx越界,不抛出异常,直接出错。 69 | deque.front(); //返回第一个数据。 70 | deque.back(); //返回最后一个数据 71 | ``` 72 | 使用方法: 73 | ```c 74 | deque deqInt; 75 | deqInt.push_back(1); 76 | deqInt.push_back(3); 77 | deqInt.push_back(5); 78 | deqInt.push_back(7); 79 | deqInt.push_back(9); 80 | 81 | int iA = deqInt.at(0); //1 82 | int iB = deqInt[1]; //3 83 | deqInt.at(0) = 99; //99 84 | deqInt[1] = 88; //88 85 | 86 | int iFront = deqInt.front(); //99 87 | int iBack = deqInt.back(); //9 88 | deqInt.front() = 77; //77 89 | deqInt.back() = 66; //66 90 | ``` 91 | 92 | ### 5、deque与迭代器 93 | 94 | 可通过下面这组函数获取deque的首尾位置迭代器: 95 | ```c 96 | deque.begin(); //返回容器中第一个元素的迭代器。 97 | deque.end(); //返回容器中最后一个元素之后的迭代器。 98 | deque.rbegin(); //返回容器中倒数第一个元素的迭代器。 99 | deque.rend(); //返回容器中倒数最后一个元素之后的迭代器。 100 | ``` 101 | 102 | 使用方法如下: 103 | ```c 104 | deque deqInt; 105 | deqInt.push_back(1); 106 | deqInt.push_back(3); 107 | deqInt.push_back(5); 108 | deqInt.push_back(7); 109 | deqInt.push_back(9); 110 | 111 | for (deque::iterator it=deqInt.begin(); it!=deqInt.end(); ++it) 112 | { 113 | cout << *it; 114 | cout << ""; 115 | } 116 | // 1 3 5 7 9 117 | 118 | for (deque::reverse_iterator rit=deqInt.rbegin(); rit!=deqInt.rend(); ++rit) 119 | { 120 | cout << *rit; 121 | cout << ""; 122 | } 123 | //9 7 5 3 1 124 | ``` 125 | 126 | ### 6、deque的带参构造函数 127 | 128 | 函数原型如下: 129 | ```c 130 | deque(beg,end); //构造函数将[beg, end)区间中的元素拷贝给本身。注意该区间是左闭右开的区间。 131 | deque(n,elem); //构造函数将n个elem拷贝给本身。 132 | deque(const deque &deq); //拷贝构造函数。 133 | ``` 134 | 使用方法: 135 | ```c 136 | deque deqIntA; 137 | deqIntA.push_back(1); 138 | deqIntA.push_back(3); 139 | deqIntA.push_back(5); 140 | deqIntA.push_back(7); 141 | deqIntA.push_back(9); 142 | 143 | deque deqIntB(deqIntA.begin(),deqIntA.end()); //1 3 5 7 9 144 | deque deqIntC(5,8); //8 8 8 8 8 145 | deque deqIntD(deqIntA); //1 3 5 7 9 146 | ``` 147 | 148 | ### 7、deque的赋值 149 | 150 | 可以通过下面这些函数对deque对象进行赋值: 151 | ```c 152 | deque.assign(beg,end); //将[beg, end)区间中的数据拷贝赋值给本身。注意该区间是左闭右开的区间。 153 | deque.assign(n,elem); //将n个elem拷贝赋值给本身。 154 | deque& operator=(const deque &deq); //重载等号操作符 155 | deque.swap(deq); // 将vec与本身的元素互换 156 | ``` 157 | 158 | 使用方法如下: 159 | ```c 160 | deque deqIntA,deqIntB,deqIntC,deqIntD; 161 | deqIntA.push_back(1); 162 | deqIntA.push_back(3); 163 | deqIntA.push_back(5); 164 | deqIntA.push_back(7); 165 | deqIntA.push_back(9); 166 | 167 | deqIntB.assign(deqIntA.begin(),deqIntA.end()); // 1 3 5 7 9 168 | 169 | deqIntC.assign(5,8); //8 8 8 8 8 170 | 171 | deqIntD = deqIntA; //1 3 5 7 9 172 | 173 | deqIntC.swap(deqIntD); //互换 174 | ``` 175 | 176 | ### 8、deque的大小 177 | 178 | 和vector类似: 179 | ```c 180 | deque.size(); //返回容器中元素的个数 181 | deque.empty(); //判断容器是否为空 182 | deque.resize(num); //重新指定容器的长度为num,若容器变长,则以默认值填充新位置。如果容器变短,则末尾超出容器长度的元素被删除。 183 | deque.resize(num, elem); //重新指定容器的长度为num,若容器变长,则以elem值填充新位置。如果容器变短,则末尾超出容器长度的元素被删除。 184 | ``` 185 | 186 | 使用方法: 187 | ```c 188 | deque deqIntA; 189 | deqIntA.push_back(1); 190 | deqIntA.push_back(3); 191 | deqIntA.push_back(5); 192 | 193 | int iSize = deqIntA.size(); //3 194 | 195 | if (!deqIntA.empty()) 196 | { 197 | deqIntA.resize(5); //1 3 5 0 0 198 | deqIntA.resize(7,1); //1 3 5 0 0 1 1 199 | deqIntA.resize(2); //1 3 200 | } 201 | ``` 202 | 203 | ### 9、deque插入元素 204 | 205 | 可通过下面这组函数对deque对象进行插入操作: 206 | ```c 207 | deque.insert(pos,elem); //在pos位置插入一个elem元素的拷贝,返回新数据的位置。 208 | deque.insert(pos,n,elem); //在pos位置插入n个elem数据,无返回值。 209 | deque.insert(pos,beg,end); //在pos位置插入[beg,end)区间的数据,无返回值。 210 | ``` 211 | 使用方法: 212 | ```c 213 | deque deqA; 214 | deque deqB; 215 | 216 | deqA.push_back(1); 217 | deqA.push_back(3); 218 | deqA.push_back(5); 219 | deqA.push_back(7); 220 | deqA.push_back(9); 221 | 222 | deqB.push_back(2); 223 | deqB.push_back(4); 224 | deqB.push_back(6); 225 | deqB.push_back(8); 226 | 227 | deqA.insert(deqA.begin(), 11); //{11, 1, 3, 5, 7, 9} 228 | deqA.insert(deqA.begin()+1,2,33); //{11,33,33,1,3,5,7,9} 229 | deqA.insert(deqA.begin() , deqB.begin() , deqB.end() ); //{2,4,6,8,11,33,33,1,3,5,7,9} 230 | ``` 231 | 232 | ### 10、deque删除元素 233 | 234 | 操作函数如下: 235 | ```c 236 | deque.clear(); //移除容器的所有数据 237 | deque.erase(beg,end); //删除[beg,end)区间的数据,返回下一个数据的位置。 238 | deque.erase(pos); //删除pos位置的数据,返回下一个数据的位置。 239 | ``` 240 | 241 | 假设deqInt是用deque声明的容器,现已包含按顺序的1,3,5,6,9元素,然后进行如下操作: 242 | ```c 243 | deque::iterator itBegin=deqInt.begin()+1; 244 | deque::iterator itEnd=deqInt.begin()+3; 245 | deqInt.erase(itBegin,itEnd); 246 | ``` 247 | 此时容器deqInt包含按顺序的1,6,9三个元素。 248 | 249 | 再次假设 deqInt 包含1,3,2,3,3,3,4,3,5,3,删除容器中等于3的元素: 250 | ```c 251 | for(deque::iterator it=deqInt.being(); it!=deqInt.end(); ) //小括号里不需写 ++it 252 | { 253 | if(*it == 3) 254 | { 255 | it = deqInt.erase(it); //以迭代器为参数,删除元素3,并把数据删除后的下一个元素位置返回给迭代器。此时不执行 ++it; 256 | } 257 | else 258 | { 259 | ++it; 260 | } 261 | } 262 | ``` 263 | 264 | 删除deqInt的所有元素: 265 | ```c 266 | deqInt.clear(); //容器为空 267 | ``` 268 | 269 | ### 11、使用案例 270 | 271 | 见src下相关代码文件。 -------------------------------------------------------------------------------- /03.STL/01.STL使用/deque/src/75.stl_deque.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hujiese/cpp-study/c94ec4adf61a059e7e768cabc2bcb7b276327bd6/03.STL/01.STL使用/deque/src/75.stl_deque.cpp -------------------------------------------------------------------------------- /03.STL/01.STL使用/heap/README.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | - [heap--堆](#heap--%E5%A0%86) 5 | - [一、堆与堆排序](#%E4%B8%80%E5%A0%86%E4%B8%8E%E5%A0%86%E6%8E%92%E5%BA%8F) 6 | - [二、STL堆操作函数](#%E4%BA%8Cstl%E5%A0%86%E6%93%8D%E4%BD%9C%E5%87%BD%E6%95%B0) 7 | - [1、概述](#1%E6%A6%82%E8%BF%B0) 8 | - [2、函数使用](#2%E5%87%BD%E6%95%B0%E4%BD%BF%E7%94%A8) 9 | - [(1)make_heap -- 是生成一个堆,大顶堆或小顶堆](#1make_heap----%E6%98%AF%E7%94%9F%E6%88%90%E4%B8%80%E4%B8%AA%E5%A0%86%E5%A4%A7%E9%A1%B6%E5%A0%86%E6%88%96%E5%B0%8F%E9%A1%B6%E5%A0%86) 10 | - [(2)push_heap -- 向堆中插入一个元素,并且使堆的规则依然成立](#2push_heap----%E5%90%91%E5%A0%86%E4%B8%AD%E6%8F%92%E5%85%A5%E4%B8%80%E4%B8%AA%E5%85%83%E7%B4%A0%E5%B9%B6%E4%B8%94%E4%BD%BF%E5%A0%86%E7%9A%84%E8%A7%84%E5%88%99%E4%BE%9D%E7%84%B6%E6%88%90%E7%AB%8B) 11 | - [(3)pop_heap -- 在堆的基础上弹出堆顶元素](#3pop_heap----%E5%9C%A8%E5%A0%86%E7%9A%84%E5%9F%BA%E7%A1%80%E4%B8%8A%E5%BC%B9%E5%87%BA%E5%A0%86%E9%A1%B6%E5%85%83%E7%B4%A0) 12 | - [(4)sort_heap -- 堆排序](#4sort_heap----%E5%A0%86%E6%8E%92%E5%BA%8F) 13 | - [(5)is_heap -- 判断数组是否是一个堆](#5is_heap----%E5%88%A4%E6%96%AD%E6%95%B0%E7%BB%84%E6%98%AF%E5%90%A6%E6%98%AF%E4%B8%80%E4%B8%AA%E5%A0%86) 14 | - [(6)is_heap_until -- 获取区间中第一个不满足heap条件的位置](#6is_heap_until----%E8%8E%B7%E5%8F%96%E5%8C%BA%E9%97%B4%E4%B8%AD%E7%AC%AC%E4%B8%80%E4%B8%AA%E4%B8%8D%E6%BB%A1%E8%B6%B3heap%E6%9D%A1%E4%BB%B6%E7%9A%84%E4%BD%8D%E7%BD%AE) 15 | - [3、综合案例:](#3%E7%BB%BC%E5%90%88%E6%A1%88%E4%BE%8B) 16 | - [4、总结](#4%E6%80%BB%E7%BB%93) 17 | 18 | 19 | 20 | ## heap--堆 21 | 22 | ### 一、堆与堆排序 23 | 24 | 关于堆和堆排序的概念可参考这篇文章: 25 | [堆和堆排序:为什么说堆排序没有快速排序快](./img/heap.png) 26 | > https://blog.csdn.net/every__day/article/details/86580883 27 | 28 | ### 二、STL堆操作函数 29 | 30 | 该部分参考: 31 | 32 | [make_heap(), pop_heap(), push_heap()用法](https://blog.csdn.net/qq_29630271/article/details/66478256) 33 | 34 | [STL中heap相关函数的用法:make_heap,push_heap,pop_heap,sort heap](https://blog.csdn.net/qq_34793133/article/details/81222919) 35 | 36 | #### 1、概述 37 | 38 | 在STL中,heap是算法的形式提供给我们使用的。包括下面几个函数: 39 | 40 | 函数|功能|时间复杂度 41 | ---|---|--- 42 | make_heap|根据指定的迭代器区间以及一个可选的比较函数,来创建一个heap|O(N) 43 | push_heap|把指定区间的最后一个元素插入到heap中|O(logN) 44 | pop_heap |弹出heap顶元素, 将其放置于区间末尾|O(logN) 45 | sort_heap|堆排序算法,通常通过反复调用pop_heap来实现|N*O(logN) 46 | 47 | 48 | C++11加入了两个新成员: 49 | 50 | 函数|功能|时间复杂度 51 | ---|---|--- 52 | is_heap|判断给定区间是否是一个heap|O(N) 53 | is_heap_until|找出区间中第一个不满足heap条件的位置|O(N) 54 | 55 | 因为heap以算法的形式提供,所以要使用这几个api需要包含 #include\ 56 | 57 | #### 2、函数使用 58 | 59 | ##### (1)make_heap -- 是生成一个堆,大顶堆或小顶堆 60 | 61 | STL中的通过make_heap创建的堆,默认是大顶堆(max heap),即每个非叶子节点元素的值均不”小于”(默认使用<作为比较准则)其左右孩子节点。要改变堆的建立准则,可以自己制定一个比较函数,如下第二个版本的make_heap声明: 62 | 63 | ```cpp 64 | 65 | // 1 默认生成大顶堆 66 | template< class RandomIt > 67 | void make_heap( RandomIt first, RandomIt last ); 68 | 69 | // 2 _Compare有两种参数,一种是greater(生成小顶堆),一种是less(生成大顶堆) 70 | template< class RandomIt, class Compare > 71 | void make_heap( RandomIt first, RandomIt last, Compare comp ); 72 | ``` 73 | 74 | 案例: 75 | 76 | ```cpp 77 | vector vi{6, 1, 2, 5, 3, 4}; 78 | printContainer(vi, "vi: "); // vi: 6 1 2 5 3 4 79 | 80 | make_heap(vi.begin(), vi.end()); 81 | printContainer(vi, "vi: "); // vi: 6 5 4 1 3 2 82 | 83 | //------------------------------------------------- 84 | 85 | vector v2{6, 1, 2, 5, 3, 4}; 86 | printContainer(v2, "v2 before make_heap: ");// v2 before make_heap: 6 1 2 5 3 4 87 | make_heap(v2.begin(), v2.end(), greater()); 88 | printContainer(v2, "v2 after make_heap: ");// v2 after make_heap: 1 3 2 5 6 4 89 | // 这里使用了greater()来代替默认的less()来创建int类型的heap。可以按层次遍历的顺序把这个heap画出来,可以看到它跟默认情况刚好相反,会是一个小顶堆。 90 | ``` 91 | 92 | ##### (2)push_heap -- 向堆中插入一个元素,并且使堆的规则依然成立 93 | 94 | ```cpp 95 | // 1 默认为大顶堆 96 | template< class RandomIt > 97 | void push_heap( RandomIt first, RandomIt last ); 98 | 99 | // 2 _Compare有两种参数,一种是greater(小顶堆),一种是less(大顶堆) 100 | template< class RandomIt, class Compare > 101 | void push_heap( RandomIt first, RandomIt last, Compare comp ); 102 | ``` 103 | 104 | 注意: 105 | 106 | * 调用push_heap之前必须调用make_heap创建一个堆。 107 | * 首先数组push_back插入元素,然后再调用push_heap,它会使最后一个元素插到合适位置。 108 | * push_heap中的_Compare和make_heap中的_Compare参数必须是一致的,不然会插入堆失败,最后一个元素还是在最后位置,导致插入失败。 109 | 110 | 案例: 111 | 112 | ```cpp 113 | vector v1{6, 1, 2, 5, 3, 4}; 114 | make_heap(v1.begin(), v1.end()); 115 | 116 | v1.push_back(200); 117 | printContainer(v1, "before push_heap: "); // before push_heap: 6 5 4 1 3 2 200 118 | push_heap(v1.begin(), v1.end()); 119 | printContainer(v1, "after push_heap: "); // after push_heap: 200 5 6 1 3 2 4 120 | ``` 121 | 122 | 先用make_heap来构造一个堆,然后在容器末尾追加元素之后,把新的迭代器区间传给push_heap,这样新尾部元素也被添加到堆中。 123 | 124 | 注意:在使用push_heap(f, l)前,调用者需要确保[f, l-1)已经是一个堆. push_heap(f, l)仅仅会把*(l-1)插入到[f, l-1)这个区间形成的堆中,时间复杂度是O(logN)。 125 | 126 | 下面演示一开始不用make_heap处理,直接push_heap的情况: 127 | 128 | ```cpp 129 | vector v2{6, 1, 2, 5, 3, 4}; 130 | v2.push_back(200); 131 | printContainer(v2, "v2 before push_heap: ");// v2 before push_heap: 6 1 2 5 3 4 200 132 | push_heap(v2.begin(), v2.end()); 133 | printContainer(v2, "v2 after push_heap: ");// v2 after push_heap: 200 1 6 5 3 4 2 134 | ``` 135 | 136 | 可以看出直接调用push_heap的结果并不是一个heap. 下面的pop_heap也有同样。 137 | 138 | ##### (3)pop_heap -- 在堆的基础上弹出堆顶元素 139 | 140 | ```cpp 141 | // 1 默认为大顶堆 142 | template< class RandomIt > 143 | void pop_heap( RandomIt first, RandomIt last ); 144 | 145 | // 2 _Compare有两种参数,一种是greater(小顶堆),一种是less(大顶堆) 146 | template< class RandomIt, class Compare > 147 | void pop_heap( RandomIt first, RandomIt last, Compare comp ); 148 | ``` 149 | 例如,pop_heap(nums.begin(), nums.end(),greater()),它会将堆顶元素(即为数组第一个位置)和数组最后一个位置对调,然后你可以调用数组pop_back,删除这个元素,需要注意的是,调用者要保证,在调用pop_heap时[first, last)已经是一个堆(使用相同的排序准则): 150 | 151 | ```cpp 152 | vector v1{6, 1, 2, 5, 3, 4}; 153 | make_heap(v1.begin(), v1.end()); 154 | printContainer(v1, "after make_heap: ");// after make_heap: 6 5 4 1 3 2 155 | 156 | pop_heap(v1.begin(), v1.end()); 157 | printContainer(v1, "after pop_heap: ");// after pop_heap: 5 3 4 1 2 6 158 | 159 | auto largest = v1.back(); 160 | psln(largest);// largest = 6 161 | v1.pop_back(); 162 | printContainer(v1, "delete largest: ");// delete largest: 5 3 4 1 2 163 | ``` 164 | 165 | 注意,pop_heap中的_Compare和make_heap中的_Compare参数必须是一致的,不然会失败。 166 | 167 | ##### (4)sort_heap -- 堆排序 168 | ```cpp 169 | // 1 170 | template< class RandomIt > 171 | void sort_heap( RandomIt first, RandomIt last ); 172 | 173 | // 2 174 | template< class RandomIt, class Compare > 175 | void sort_heap( RandomIt first, RandomIt last, Compare comp ); 176 | ``` 177 | 178 | sort_heap即经典的堆排序算法,通过每次弹出堆顶直到堆为空,依次被弹出的元素就组成了有序的序列了。STL中的priority_queue即使用heap的这个特性来实现。 179 | 180 | 使用sort_heap(f, l)处理过的区间因为已经有序,就不再是一个heap了: 181 | ```cpp 182 | vector v1{6, 1, 2, 5, 3, 4}; 183 | printContainer(v1, "before sort_heap: ");// before sort_heap: 6 1 2 5 3 4 184 | 185 | make_heap(v1.begin(), v1.end()); 186 | 187 | sort_heap(v1.begin(), v1.end()); 188 | printContainer(v1, "after sort_heap: ");// after sort_heap: 1 2 3 4 5 6 189 | ``` 190 | 注意: 191 | 192 | * 调用者仍需确保区间已经是一个堆。 193 | * make_heap和sort_heap的Compare参数要一致。 194 | 195 | ##### (5)is_heap -- 判断数组是否是一个堆 196 | 197 | ```cpp 198 | // (1) (since C++11) 199 | template< class RandomIt > 200 | bool is_heap( RandomIt first, RandomIt last ); 201 | 202 | // (2) (since C++11) 203 | template< class RandomIt, class Compare > 204 | bool is_heap( RandomIt first, RandomIt last, Compare comp ); 205 | ``` 206 | 使用方法: 207 | 208 | ```cpp 209 | vector v1{6, 1, 2, 5, 3, 4}; 210 | psln(is_heap(v1.begin(), v1.end()));// is_heap(v1.begin(), v1.end()) = 0 211 | 212 | pln("after make_heap");// after make_heap 213 | 214 | make_heap(v1.begin(), v1.end()); 215 | psln(is_heap(v1.begin(), v1.end()));// is_heap(v1.begin(), v1.end()) = 1 216 | ``` 217 | 218 | ##### (6)is_heap_until -- 获取区间中第一个不满足heap条件的位置 219 | 220 | ```cpp 221 | // (1) (since C++11) 222 | template< class RandomIt > 223 | RandomIt is_heap_until( RandomIt first, RandomIt last ); 224 | 225 | // (2) (since C++11) 226 | template< class RandomIt, class Compare > 227 | RandomIt is_heap_until( RandomIt first, RandomIt last, Compare comp ); 228 | ``` 229 | 230 | 使用方法: 231 | 232 | ```cpp 233 | vector v1{6, 1, 2, 5, 3, 4}; 234 | auto iter = is_heap_until(v1.begin(), v1.end()); 235 | psln(*iter); // *iter = 5 5 是第一个不满足heap条件的位置。 236 | 237 | make_heap(v1.begin(), v1.end()); 238 | iter = is_heap_until(v1.begin(), v1.end()); 239 | ASSERT_TRUE(iter == v1.end()); 240 | ``` 241 | #### 3、综合案例: 242 | 243 | ```cpp 244 | # include 245 | # include 246 | # include 247 | # include 248 | 249 | using namespace std; 250 | 251 | void printVec(vector nums) 252 | { 253 | for (int i = 0; i < nums.size(); ++i) 254 | cout << nums[i] << " "; 255 | cout << endl; 256 | } 257 | int main(void) 258 | { 259 | int nums_temp[] = { 8, 3, 4, 8, 9, 2, 3, 4, 10 }; 260 | vector nums(nums_temp, nums_temp + 9); 261 | cout << "make_heap之前: "; 262 | printVec(nums); 263 | 264 | cout << "(默认(less))make_heap: "; 265 | make_heap(nums.begin(), nums.end()); 266 | printVec(nums); 267 | 268 | cout << "(less)make_heap: "; 269 | make_heap(nums.begin(), nums.end(), less()); 270 | printVec(nums); 271 | 272 | cout << "(greater)make_heap: "; 273 | make_heap(nums.begin(), nums.end(), greater()); 274 | printVec(nums); 275 | 276 | cout << "此时,nums为小顶堆 greater" << endl; 277 | cout << "push_back(3)" << endl; 278 | nums.push_back(3); 279 | //cout << "默认(less)push_heap 此时push_heap失败: "; 280 | //push_heap(nums.begin(), nums.end()); 281 | //printVec(nums); 282 | cout << "push_heap为greater 和make_heap一致,此时push_heap成功: "; 283 | push_heap(nums.begin(), nums.end(), greater()); 284 | printVec(nums); 285 | cout << "(greater,不然会失败)pop_heap: "; 286 | pop_heap(nums.begin(), nums.end(), greater()); 287 | printVec(nums); 288 | cout << "pop_back(): "; 289 | nums.pop_back(); 290 | printVec(nums); 291 | 292 | 293 | cout << "--------------------------------sort---------------------------" << endl; 294 | vector v1{ 6, 1, 2, 5, 3, 4 }; 295 | cout << "before sort_heap: "; 296 | printVec(v1); 297 | 298 | make_heap(v1.begin(), v1.end(), greater()); 299 | 300 | // sort_heap(v1.begin(), v1.end()); 301 | sort_heap(v1.begin(), v1.end(), greater()); 302 | cout << "after sort_heap: "; 303 | printVec(v1); 304 | } 305 | ``` 306 | 307 | 结果如下: 308 | 309 | ``` 310 | make_heap之前: 8 3 4 8 9 2 3 4 10 311 | (默认(less))make_heap: 10 9 4 8 8 2 3 4 3 312 | (less)make_heap: 10 9 4 8 8 2 3 4 3 313 | (greater)make_heap: 2 3 3 4 8 4 10 9 8 314 | 此时,nums为小顶堆 greater 315 | push_back(3) 316 | push_heap为greater 和make_heap一致,此时push_heap成功: 2 3 3 4 3 4 10 9 8 8 317 | (greater,不然会失败)pop_heap: 3 3 4 4 3 8 10 9 8 2 318 | pop_back(): 3 3 4 4 3 8 10 9 8 319 | --------------------------------sort--------------------------- 320 | before sort_heap: 6 1 2 5 3 4 321 | after sort_heap: 6 5 4 3 2 1 322 | ``` 323 | 324 | #### 4、总结 325 | 326 | * 建堆,make_heap 327 | 328 | * 堆操作:增加元素(push_heap),删除元素(pop_heap), 排序(sort_heap), 均要求区间已经是一个heap,并且是与当前操作使用相同的排序准则 329 | 330 | * is_heap, is_heap_until当做辅助判断函数来用 331 | 332 | * 所有的heap算法操作的区间都需要是随机迭代器组成 -------------------------------------------------------------------------------- /03.STL/01.STL使用/heap/img/heap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hujiese/cpp-study/c94ec4adf61a059e7e768cabc2bcb7b276327bd6/03.STL/01.STL使用/heap/img/heap.png -------------------------------------------------------------------------------- /03.STL/01.STL使用/heap/src/98.stl_heap.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hujiese/cpp-study/c94ec4adf61a059e7e768cabc2bcb7b276327bd6/03.STL/01.STL使用/heap/src/98.stl_heap.cpp -------------------------------------------------------------------------------- /03.STL/01.STL使用/list/README.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | - [STL -- list](#stl----list) 5 | - [1、介绍](#1%E4%BB%8B%E7%BB%8D) 6 | - [2、默认构造函数](#2%E9%BB%98%E8%AE%A4%E6%9E%84%E9%80%A0%E5%87%BD%E6%95%B0) 7 | - [3、在列表头尾操作元素](#3%E5%9C%A8%E5%88%97%E8%A1%A8%E5%A4%B4%E5%B0%BE%E6%93%8D%E4%BD%9C%E5%85%83%E7%B4%A0) 8 | - [4、获取列表头尾数据](#4%E8%8E%B7%E5%8F%96%E5%88%97%E8%A1%A8%E5%A4%B4%E5%B0%BE%E6%95%B0%E6%8D%AE) 9 | - [5、列表与迭代器](#5%E5%88%97%E8%A1%A8%E4%B8%8E%E8%BF%AD%E4%BB%A3%E5%99%A8) 10 | - [6、带参构造函数](#6%E5%B8%A6%E5%8F%82%E6%9E%84%E9%80%A0%E5%87%BD%E6%95%B0) 11 | - [7、赋值函数](#7%E8%B5%8B%E5%80%BC%E5%87%BD%E6%95%B0) 12 | - [8、列表大小](#8%E5%88%97%E8%A1%A8%E5%A4%A7%E5%B0%8F) 13 | - [9、插入元素](#9%E6%8F%92%E5%85%A5%E5%85%83%E7%B4%A0) 14 | - [10、删除元素](#10%E5%88%A0%E9%99%A4%E5%85%83%E7%B4%A0) 15 | - [11、列表反转](#11%E5%88%97%E8%A1%A8%E5%8F%8D%E8%BD%AC) 16 | - [12、使用案例](#12%E4%BD%BF%E7%94%A8%E6%A1%88%E4%BE%8B) 17 | 18 | 19 | 20 | ## STL -- list 21 | 22 | ### 1、介绍 23 | 24 | * list是一个双向链表容器,可高效地进行插入删除元素。 25 | * list不可以随机存取元素,所以不支持at.(pos)函数与[]操作符(只能使用迭代器it++,it+5这样随意获取是不被允许的,只能按照顺序访问容器中的元素)。 26 | 27 | ### 2、默认构造函数 28 | 29 | list采用采用模板类实现,对象的默认构造形式: 30 | ```c 31 | list lstT; //尖括号内可以设置指针类型或自定义类型。 32 | list lstInt; //定义一个存放int的list容器。 33 | list lstFloat; //定义一个存放float的list容器。 34 | list lstString; //定义一个存放string的list容器。 35 | ``` 36 | 37 | ### 3、在列表头尾操作元素 38 | 39 | 操作函数如下所示: 40 | ```c 41 | list.push_back(elem); //在容器尾部加入一个元素 42 | list.pop_back(); //删除容器中最后一个元素 43 | list.push_front(elem); //在容器开头插入一个元素 44 | list.pop_front(); //从容器开头移除第一个元素 45 | ``` 46 | 使用方法: 47 | ```c 48 | list lstInt; 49 | lstInt.push_back(1); 50 | lstInt.push_back(3); 51 | lstInt.push_back(5); 52 | lstInt.push_back(7); 53 | lstInt.push_back(9); 54 | lstInt.pop_front(); 55 | lstInt.pop_front(); 56 | lstInt.push_front(11); 57 | lstInt.push_front(13); 58 | lstInt.pop_back(); 59 | lstInt.pop_back(); 60 | // lstInt {13,11,5} 61 | ``` 62 | 63 | ### 4、获取列表头尾数据 64 | 65 | 操作函数如下: 66 | ```c 67 | list.front(); //返回第一个元素。 68 | list.back(); //返回最后一个元素。 69 | ``` 70 | 使用方法: 71 | ```c 72 | list lstInt; 73 | lstInt.push_back(1); 74 | lstInt.push_back(3); 75 | lstInt.push_back(5); 76 | lstInt.push_back(7); 77 | lstInt.push_back(9); 78 | 79 | int iFront = lstInt.front(); //1 80 | int iBack = lstInt.back(); //9 81 | lstInt.front() = 11; //11 82 | lstInt.back() = 19; //19 83 | ``` 84 | 85 | ### 5、列表与迭代器 86 | 87 | 相关函数如下所示: 88 | ```c 89 | list.begin(); //返回容器中第一个元素的迭代器。 90 | list.end(); //返回容器中最后一个元素之后的迭代器。 91 | list.rbegin(); //返回容器中倒数第一个元素的迭代器。 92 | list.rend(); //返回容器中倒数最后一个元素的后面的迭代器。 93 | ``` 94 | 使用方法: 95 | ```c 96 | list lstInt; 97 | lstInt.push_back(1); 98 | lstInt.push_back(3); 99 | lstInt.push_back(5); 100 | lstInt.push_back(7); 101 | lstInt.push_back(9); 102 | 103 | for (list::iterator it=lstInt.begin(); it!=lstInt.end(); ++it) 104 | { 105 | cout << *it; 106 | cout << " "; 107 | } 108 | 109 | for (list::reverse_iterator rit=lstInt.rbegin(); rit!=lstInt.rend(); ++rit) 110 | { 111 | cout << *rit; 112 | cout << " "; 113 | } 114 | ``` 115 | 116 | ### 6、带参构造函数 117 | 118 | 函数定义如下: 119 | ```c 120 | list(beg,end); //构造函数将[beg, end)区间中的元素拷贝给本身。注意该区间是左闭右开的区间。 121 | list(n,elem); //构造函数将n个elem拷贝给本身。 122 | list(const list &lst); //拷贝构造函数。 123 | ``` 124 | 使用方法: 125 | ```c 126 | list lstIntA; 127 | lstIntA.push_back(1); 128 | lstIntA.push_back(3); 129 | lstIntA.push_back(5); 130 | lstIntA.push_back(7); 131 | lstIntA.push_back(9); 132 | 133 | list lstIntB(lstIntA.begin(),lstIntA.end()); //1 3 5 7 9 134 | list lstIntC(5,8); //8 8 8 8 8 135 | list lstIntD(lstIntA); //1 3 5 7 9 136 | ``` 137 | 138 | ### 7、赋值函数 139 | 140 | 操作函数如下所示: 141 | ```c 142 | list.assign(beg,end); //将[beg, end)区间中的数据拷贝赋值给本身。注意该区间是左闭右开的区间。 143 | list.assign(n,elem); //将n个elem拷贝赋值给本身。 144 | list& operator=(const list &lst); //重载等号操作符 145 | list.swap(lst); // 将lst与本身的元素互换。 146 | ``` 147 | 使用方法: 148 | ```c 149 | list lstIntA,lstIntB,lstIntC,lstIntD; 150 | lstIntA.push_back(1); 151 | lstIntA.push_back(3); 152 | lstIntA.push_back(5); 153 | lstIntA.push_back(7); 154 | lstIntA.push_back(9); 155 | 156 | lstIntB.assign(lstIntA.begin(),lstIntA.end()); //1 3 5 7 9 157 | lstIntC.assign(5,8); //8 8 8 8 8 158 | lstIntD = lstIntA; //1 3 5 7 9 159 | lstIntC.swap(lstIntD); //互换 160 | ``` 161 | ### 8、列表大小 162 | 163 | 操作函数定义如下: 164 | ```c 165 | list.size(); //返回容器中元素的个数 166 | list.empty(); //判断容器是否为空 167 | list.resize(num); //重新指定容器的长度为num,若容器变长,则以默认值填充新位置。如果容器变短,则末尾超出容器长度的元素被删除。 168 | list.resize(num, elem); //重新指定容器的长度为num,若容器变长,则以elem值填充新位置。如果容器变短,则末尾超出容器长度的元素被删除。 169 | ``` 170 | 使用方法: 171 | ```c 172 | list lstIntA; 173 | lstIntA.push_back(1); 174 | lstIntA.push_back(3); 175 | lstIntA.push_back(5); 176 | 177 | if (!lstIntA.empty()) 178 | { 179 | int iSize = lstIntA.size(); //3 180 | lstIntA.resize(5); //1 3 5 0 0 181 | lstIntA.resize(7,1); //1 3 5 0 0 1 1 182 | lstIntA.resize(2); //1 3 183 | } 184 | ``` 185 | 186 | ### 9、插入元素 187 | 188 | 操作函数如下所示: 189 | ```c 190 | list.insert(pos,elem); //在pos位置插入一个elem元素的拷贝,返回新数据的位置。 191 | list.insert(pos,n,elem); //在pos位置插入n个elem数据,无返回值。 192 | list.insert(pos,beg,end); //在pos位置插入[beg,end)区间的数据,无返回值。 193 | ``` 194 | 195 | 使用方法: 196 | ```c 197 | list lstA; 198 | list lstB; 199 | 200 | lstA.push_back(1); 201 | lstA.push_back(3); 202 | lstA.push_back(5); 203 | lstA.push_back(7); 204 | lstA.push_back(9); 205 | 206 | lstB.push_back(2); 207 | lstB.push_back(4); 208 | lstB.push_back(6); 209 | lstB.push_back(8); 210 | 211 | lstA.insert(lstA.begin(), 11); //{11, 1, 3, 5, 7, 9} 212 | lstA.insert(++lstA.begin(),2,33); //{11,33,33,1,3,5,7,9} 213 | lstA.insert(lstA.begin() , lstB.begin() , lstB.end() ); //{2,4,6,8,11,33,33,1,3,5,7,9} 214 | ``` 215 | 216 | ### 10、删除元素 217 | 218 | 操作函数如下所示: 219 | ```c 220 | list.clear(); //移除容器的所有数据 221 | list.erase(beg,end); //删除[beg,end)区间的数据,返回下一个数据的位置。 222 | list.erase(pos); //删除pos位置的数据,返回下一个数据的位置。 223 | lst.remove(elem); //删除容器中所有与elem值匹配的元素。 224 | ``` 225 | 226 | 假设lstInt是用list声明的容器,现已包含按顺序的1,3,5,6,9元素,然后进行如下操作: 227 | ```c 228 | list::iterator itBegin=lstInt.begin(); 229 | ++itBegin; 230 | list::iterator itEnd=lstInt.begin(); 231 | ++itEnd; 232 | ++itEnd; 233 | ++itEnd; 234 | lstInt.erase(itBegin,itEnd); 235 | //此时容器lstInt包含按顺序的1,6,9三个元素。 236 | ``` 237 | 238 | 再假设 lstInt 包含1,3,2,3,3,3,4,3,5,3,删除容器中等于3的元素的方法一: 239 | ```c 240 | for(list::iterator it=lstInt.being(); it!=lstInt.end(); ) //小括号里不需写 ++it 241 | { 242 | if(*it == 3) 243 | { 244 | it = lstInt.erase(it); //以迭代器为参数,删除元素3,并把数据删除后的下一个元素位置返回给迭代器,此时不执行 ++it; 245 | } 246 | else 247 | { 248 | ++it; 249 | } 250 | } 251 | ``` 252 | 253 | 删除容器中等于3的元素的方法二: 254 | ```c 255 | lstInt.remove(3); 256 | ``` 257 | 258 | 删除lstInt的所有元素: 259 | ```c 260 | lstInt.clear(); //容器为空 261 | ``` 262 | 263 | ### 11、列表反转 264 | 265 | 操作函数如下: 266 | ```c 267 | lst.reverse(); //反转链表,比如lst包含1,3,5元素,运行此方法后,lst就包含5,3,1元素。 268 | ``` 269 | 270 | 使用方法: 271 | ```c 272 | list lstA; 273 | 274 | lstA.push_back(1); 275 | lstA.push_back(3); 276 | lstA.push_back(5); 277 | lstA.push_back(7); 278 | lstA.push_back(9); 279 | 280 | lstA.reverse(); //9 7 5 3 1 281 | ``` 282 | 283 | ### 12、使用案例 284 | 285 | 详见src下源码。 -------------------------------------------------------------------------------- /03.STL/01.STL使用/list/src/79.stl_list.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hujiese/cpp-study/c94ec4adf61a059e7e768cabc2bcb7b276327bd6/03.STL/01.STL使用/list/src/79.stl_list.cpp -------------------------------------------------------------------------------- /03.STL/01.STL使用/map/README.md: -------------------------------------------------------------------------------- 1 | ## STL -- map/multimap 2 | 3 | ### 1、介绍 4 | 5 | * map是标准的关联式容器,一个map是一个键值对序列,即(key,value)对。它提供基于key的快速检索能力。 6 | * map中key值是唯一的。集合中的元素按一定的顺序排列。元素插入过程是按排序规则插入,所以不能指定插入位置。 7 | * map的具体实现采用红黑树变体的平衡二叉树的数据结构。在插入操作和删除操作上比vector快。 8 | * map可以直接存取key所对应的value,支持[]操作符,如map[key]=value。 9 | * multimap与map的区别:map支持唯一键值,每个键只能出现一次;而multimap中相同键可以出现多次。multimap不支持[]操作符。 10 | 11 | ### 2、默认构造函数 12 | 13 | map/multimap采用模板类实现,对象的默认构造形式: 14 | ```c 15 | map mapTT; //其中T1,T2可以用各种指针类型或自定义类型 16 | multimap multimapTT; 17 | ``` 18 | 如: 19 | ```c 20 | map mapA; 21 | map mapB; 22 | ``` 23 | 24 | ### 3、map的插入与迭代器 25 | 26 | 可通过insert函数来向map插入元素: 27 | ```c 28 | map.insert(...); //往容器插入元素,返回pair 29 | ``` 30 | 在map中插入元素有四种方式,现假设有: 31 | ```c 32 | map mapStu; 33 | ``` 34 | 35 | * 通过pair的方式插入对象: 36 | ```c 37 | mapStu.insert(pair(3,"小张")); 38 | ``` 39 | * 通过pair的方式插入对象: 40 | ```c 41 | mapStu.inset(make_pair(-1, “校长-1”)); 42 | ``` 43 | * 通过value_type的方式插入对象: 44 | ```c 45 | mapStu.insert(map::value_type(1,"小李")); 46 | ``` 47 | * 通过数组的方式插入值: 48 | ```c 49 | mapStu[3] = "小刘"; 50 | mapStu[5] = "小王"; 51 | ``` 52 | 53 | 需要注意的是,前三种方法,采用的是insert()方法,该方法返回值为pair。第四种方法虽然非常直观,但存在一个性能的问题,即插入3时,先在mapStu中查找主键为3的项,若没发现,则将一个键为3,值为初始化值的对组插入到mapStu中,然后再将值修改成“小刘”。若发现已存在3这个键,则修改这个键对应的value。试看下面这个例子: 54 | ```c 55 | string strName = mapStu[2]; //取操作或插入操作 56 | ``` 57 | 只有当mapStu存在2这个键时才是正确的取操作,否则会自动插入一个实例,键为2,值为初始化值。 58 | 59 | 使用方法: 60 | ```c 61 | map mapA; 62 | pair< map::iterator, bool > pairResult = mapA.insert(pair(3,"小张")); //插入方式一 63 | 64 | int iFirstFirst = (pairResult.first)->first; //iFirst == 3; 65 | string strFirstSecond = (pairResult.first)->second; //strFirstSecond为"小张" 66 | bool bSecond = pairResult.second; //bSecond == true; 67 | 68 | mapA.insert(map::value_type(1,"小李")); //插入方式二 69 | 70 | mapA[3] = "小刘"; //修改value 71 | mapA[5] = "小王"; //插入方式三 72 | 73 | string str1 = mapA[2]; //执行插入 string() 操作,返回的str1的字符串内容为空。 74 | string str2 = mapA[3]; //取得value,str2为"小刘" 75 | ``` 76 | 77 | ### 4、迭代器与遍历 78 | 79 | 相关函数如下: 80 | ```c 81 | map > mapA; //该容器是按键的升序方式排列元素。未指定函数对象,默认采用less函数对象。 82 | map> mapB; //该容器是按键的降序方式排列元素。 83 | ``` 84 | 其中,less与greater 可以替换成其它的函数对象functor,可编写自定义函数对象以进行自定义类型的比较,使用方法与set构造时所用的函数对象一样。 85 | ```c 86 | map.begin(); //返回容器中第一个数据的迭代器。 87 | map.end(); //返回容器中最后一个数据之后的迭代器。 88 | map.rbegin(); //返回容器中倒数第一个元素的迭代器。 89 | map.rend(); //返回容器中倒数最后一个元素的后面的迭代器。 90 | ``` 91 | 92 | 使用方法: 93 | ```c 94 | for (map::iterator it=mapA.begin(); it!=mapA.end(); ++it) 95 | { 96 | pair pr = *it; 97 | int iKey = pr.first; 98 | string strValue = pr.second; 99 | } 100 | ``` 101 | 102 | ### 5、拷贝构造与赋值 103 | 104 | 函数定义如下: 105 | ```c 106 | map(const map &mp); //拷贝构造函数 107 | map& operator=(const map &mp); //重载等号操作符 108 | map.swap(mp); //交换两个集合容器 109 | ``` 110 | 使用案例如下: 111 | ```c 112 | map mapA; 113 | mapA.insert(pair(3,"小张")); 114 | mapA.insert(pair(1,"小杨")); 115 | mapA.insert(pair(7,"小赵")); 116 | mapA.insert(pair(5,"小王")); 117 | 118 | map mapB(mapA); //拷贝构造 119 | 120 | map mapC; 121 | mapC = mapA; //赋值 122 | 123 | mapC[3] = "老张"; 124 | mapC.swap(mapA); //交换 125 | ``` 126 | 127 | ### 6、map 大小 128 | 129 | 操作函数如下: 130 | ```c 131 | map.size(); //返回容器中元素的数目 132 | map.empty();//判断容器是否为空 133 | ``` 134 | 使用方法如下: 135 | ```c 136 | map mapA; 137 | mapA.insert(pair(3,"小张")); 138 | mapA.insert(pair(1,"小杨")); 139 | mapA.insert(pair(7,"小赵")); 140 | mapA.insert(pair(5,"小王")); 141 | 142 | if (mapA.empty()) 143 | { 144 | int iSize = mapA.size(); //iSize == 4 145 | } 146 | ``` 147 | 148 | ### 7、map的删除 149 | 150 | 操作函数如下: 151 | ```c 152 | map.clear(); //删除所有元素 153 | map.erase(pos); //删除pos迭代器所指的元素,返回下一个元素的迭代器。 154 | map.erase(beg,end); //删除区间[beg,end)的所有元素 ,返回下一个元素的迭代器。 155 | map.erase(keyElem); //删除容器中key为keyElem的对组。 156 | ``` 157 | 使用方法: 158 | ```c 159 | map mapA; 160 | mapA.insert(pair(3,"小张")); 161 | mapA.insert(pair(1,"小杨")); 162 | mapA.insert(pair(7,"小赵")); 163 | mapA.insert(pair(5,"小王")); 164 | 165 | //删除区间内的元素 166 | map::iterator itBegin=mapA.begin(); 167 | ++ itBegin; 168 | ++ itBegin; 169 | map::iterator itEnd=mapA.end(); 170 | mapA.erase(itBegin,itEnd); //此时容器mapA包含按顺序的{1,"小杨"}{3,"小张"}两个元素。 171 | 172 | mapA.insert(pair(7,"小赵")); 173 | mapA.insert(pair(5,"小王")); 174 | 175 | //删除容器中第一个元素 176 | mapA.erase(mapA.begin()); //此时容器mapA包含了按顺序的{3,"小张"}{5,"小王"}{7,"小赵"}三个元素 177 | 178 | //删除容器中key为5的元素 179 | mapA.erase(5); 180 | 181 | //删除mapA的所有元素 182 | mapA.clear(); //容器为空 183 | ``` 184 | 185 | ### 8、查找 186 | 187 | 第一组操作函数如下: 188 | ```c 189 | map.find(key); // 查找键key是否存在,若存在,返回该键的元素的迭代器;若不存在,返回map.end(); 190 | map.count(keyElem); //返回容器中key为keyElem的对组个数。对map来说,要么是0,要么是1。对multimap来说,值可能大于1。 191 | ``` 192 | 193 | 使用方法: 194 | ```c 195 | map::iterator it=mapStu.find(3); 196 | if(it == mapStu.end()) 197 | { 198 | //没找到 199 | } 200 | else 201 | { 202 | //找到了 203 | pair pairStu = *it; 204 | int iID = pairStu.first; //或 int iID = it->first; 205 | string strName = pairStu.second; //或 string strName = it->second; 206 | } 207 | ``` 208 | 第二组操作函数如下: 209 | ```c 210 | map.lower_bound(keyElem); //返回第一个key>=keyElem元素的迭代器。 211 | map.upper_bound(keyElem); // 返回第一个key>keyElem元素的迭代器。 212 | ``` 213 | 假设mapStu是用map声明的容器,已包含{1,"小李"}{3,"小张"}{5,"小王"}{7,"小赵"}{9,"小陈"}元素,现做如下操作: 214 | ```c 215 | map::iterator it; 216 | it = mapStu.lower_bound(5); //it->first==5 it->second=="小王" 217 | it = mapStu.upper_bound(5); //it->first==7 it->second=="小赵" 218 | it = mapStu.lower_bound(6); //it->first==7 it->second=="小赵" 219 | it = mapStu.upper_bound(6); //it->first==7 it->second=="小赵" 220 | ``` 221 | 第三组操作函数如下: 222 | ```c 223 | map.equal_range(keyElem); //返回容器中key与keyElem相等的上下限的两个迭代器。上限是闭区间,下限是开区间,如[beg,end)。 224 | ``` 225 | 使用方法: 226 | ```c 227 | map mapStu; 228 | ... //往mapStu容器插入元素{1,"小李"}{3,"小张"}{5,"小王"}{7,"小赵"}{9,"小陈"} 229 | pair< map::iterator , map::iterator > pairIt = mapStu.equal_range(5); 230 | map::iterator itBeg = pairIt.first; 231 | map::iterator itEnd = pairIt.second; 232 | //此时 itBeg->first==5 , itEnd->first == 7, 233 | itBeg->second=="小王", itEnd->second=="小赵" 234 | ``` 235 | 236 | ### 9、使用案例 237 | 238 | 见src下源码。 -------------------------------------------------------------------------------- /03.STL/01.STL使用/map/src/84.stl_map1.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hujiese/cpp-study/c94ec4adf61a059e7e768cabc2bcb7b276327bd6/03.STL/01.STL使用/map/src/84.stl_map1.cpp -------------------------------------------------------------------------------- /03.STL/01.STL使用/map/src/85.stl_map2.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | using namespace std; 5 | 6 | void test1(void) 7 | { 8 | map mp; 9 | mp.insert(pair(1, "str1")); 10 | mp.insert(make_pair(2, "str2")); 11 | mp.insert(map::value_type(3, "str3")); 12 | mp[3] = "str4"; 13 | 14 | map::iterator it = mp.find(34); 15 | if (it == mp.end()) 16 | { 17 | cout << "we can't find the value to the key !" << endl; 18 | } 19 | else 20 | { 21 | cout << it->first << "\t" << it->second << endl; 22 | } 23 | } 24 | 25 | void test2(void) 26 | { 27 | map mp; 28 | mp.insert(pair(1, "str1")); 29 | mp.insert(make_pair(2, "str2")); 30 | mp.insert(map::value_type(3, "str3")); 31 | mp[3] = "str4"; 32 | 33 | pair::iterator, map::iterator> pt = mp.equal_range(2); 34 | if (pt.first == mp.end()) 35 | { 36 | cout << "we can't find the value to the key !" << endl; 37 | } 38 | else 39 | { 40 | cout << pt.first->first << "\t" << pt.first->second << endl; 41 | } 42 | 43 | if (pt.second == mp.end()) 44 | { 45 | cout << "we can't find the value to the key !" << endl; 46 | } 47 | else 48 | { 49 | cout << pt.second->first << "\t" << pt.second->second << endl; 50 | } 51 | } 52 | int main(void) 53 | { 54 | cout << "-----------test1-----------" << endl; 55 | test1(); 56 | cout << "-----------test2-----------" << endl; 57 | test2(); 58 | return 0; 59 | } -------------------------------------------------------------------------------- /03.STL/01.STL使用/map/src/86.stl_multimap.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | using namespace std; 5 | 6 | class Person 7 | { 8 | public: 9 | string name; 10 | int age; 11 | string tel; 12 | double salary; 13 | }; 14 | 15 | void test1(void) 16 | { 17 | Person p1, p2, p3, p4, p5; 18 | p1.name = "person1"; 19 | p1.age = 1; 20 | 21 | p2.name = "person2"; 22 | p2.age = 2; 23 | 24 | p3.name = "person3"; 25 | p3.age = 3; 26 | 27 | p4.name = "person4"; 28 | p4.age = 4; 29 | 30 | p5.name = "person5"; 31 | p5.age = 5; 32 | 33 | multimap mp; 34 | mp.insert(make_pair("sale", p1)); 35 | mp.insert(make_pair("sale", p2)); 36 | mp.insert(make_pair("development", p3)); 37 | mp.insert(make_pair("development", p4)); 38 | mp.insert(make_pair("Financial", p5)); 39 | 40 | for (multimap::iterator it = mp.begin(); it != mp.end(); it++) 41 | { 42 | cout << it->first << "\t" << it->second.name << endl; 43 | } 44 | } 45 | 46 | void test2(void) 47 | { 48 | Person p1, p2, p3, p4, p5; 49 | p1.name = "person1"; 50 | p1.age = 1; 51 | 52 | p2.name = "person2"; 53 | p2.age = 2; 54 | 55 | p3.name = "person3"; 56 | p3.age = 3; 57 | 58 | p4.name = "person4"; 59 | p4.age = 4; 60 | 61 | p5.name = "person5"; 62 | p5.age = 5; 63 | 64 | multimap mp; 65 | mp.insert(make_pair("sale", p1)); 66 | mp.insert(make_pair("sale", p2)); 67 | mp.insert(make_pair("development", p3)); 68 | mp.insert(make_pair("development", p4)); 69 | mp.insert(make_pair("Financial", p5)); 70 | 71 | multimap::iterator it = mp.find("development"); 72 | int len = mp.count("development"); 73 | int count = 0; 74 | while ((it != mp.end()) && (count < len)) 75 | { 76 | cout << it->first << "\t" << it->second.age << endl; 77 | it++; 78 | count++; 79 | } 80 | } 81 | 82 | 83 | void test3(void) 84 | { 85 | Person p1, p2, p3, p4, p5; 86 | p1.name = "person1"; 87 | p1.age = 1; 88 | 89 | p2.name = "person2"; 90 | p2.age = 2; 91 | 92 | p3.name = "person3"; 93 | p3.age = 3; 94 | 95 | p4.name = "person4"; 96 | p4.age = 4; 97 | 98 | p5.name = "person5"; 99 | p5.age = 5; 100 | 101 | multimap mp; 102 | mp.insert(make_pair("sale", p1)); 103 | mp.insert(make_pair("sale", p2)); 104 | mp.insert(make_pair("development", p3)); 105 | mp.insert(make_pair("development", p4)); 106 | mp.insert(make_pair("Financial", p5)); 107 | 108 | for (multimap::iterator it = mp.begin(); it != mp.end(); it++) 109 | { 110 | if (it->second.name == "person4") 111 | { 112 | it->second.name = "personFourth"; 113 | } 114 | } 115 | 116 | for (multimap::iterator it = mp.begin(); it != mp.end(); it++) 117 | { 118 | cout << it->first << "\t" << it->second.name << endl; 119 | } 120 | 121 | } 122 | int main(void) 123 | { 124 | cout << "-----------test1-----------" << endl; 125 | test1(); 126 | cout << "-----------test2-----------" << endl; 127 | test2(); 128 | cout << "-----------test3-----------" << endl; 129 | test3(); 130 | 131 | return 0; 132 | } -------------------------------------------------------------------------------- /03.STL/01.STL使用/priority_queue/README.md: -------------------------------------------------------------------------------- 1 | ## STL -- priority_queue(了解) 2 | 3 | 操作函数示例: 4 | ```c 5 | priority_queue> pq; 6 | priority_queue> pq; 7 | pq.empty() 8 | pq.size() 9 | pq.top() 10 | pq.pop() 11 | pq.push(item) 12 | ``` 13 | 使用案例: 14 | ```c 15 | #include 16 | #include 17 | #include 18 | using namespace std; 19 | 20 | void main() 21 | { 22 | priority_queue p1; //默认是 最大值优先级队列 23 | //priority_queue, less > p1; //相当于这样写 24 | priority_queue, greater> p2; //最小值优先级队列 25 | 26 | p1.push(33); 27 | p1.push(11); 28 | p1.push(55); 29 | p1.push(22); 30 | cout << "队列大小" << p1.size() << endl; 31 | cout << "队头" << p1.top() << endl; 32 | 33 | while (p1.size() > 0) 34 | { 35 | cout << p1.top() << " "; 36 | p1.pop(); 37 | } 38 | cout << endl; 39 | 40 | cout << "测试 最小值优先级队列" << endl; 41 | p2.push(33); 42 | p2.push(11); 43 | p2.push(55); 44 | p2.push(22); 45 | while (p2.size() > 0) 46 | { 47 | cout << p2.top() << " "; 48 | p2.pop(); 49 | 50 | } 51 | } 52 | ``` 53 | 测试结果如下: 54 | ``` 55 | 队列大小4 56 | 队头55 57 | 55 33 22 11 58 | 测试 最小值优先级队列 59 | 11 22 33 55 60 | ``` -------------------------------------------------------------------------------- /03.STL/01.STL使用/priority_queue/src/80.stl_priority_queue.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hujiese/cpp-study/c94ec4adf61a059e7e768cabc2bcb7b276327bd6/03.STL/01.STL使用/priority_queue/src/80.stl_priority_queue.cpp -------------------------------------------------------------------------------- /03.STL/01.STL使用/queue/README.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | - [STL -- queue](#stl----queue) 5 | - [1、介绍](#1%E4%BB%8B%E7%BB%8D) 6 | - [2、默认构造函数](#2%E9%BB%98%E8%AE%A4%E6%9E%84%E9%80%A0%E5%87%BD%E6%95%B0) 7 | - [3、入队和出队操作](#3%E5%85%A5%E9%98%9F%E5%92%8C%E5%87%BA%E9%98%9F%E6%93%8D%E4%BD%9C) 8 | - [4、拷贝构造函数与赋值](#4%E6%8B%B7%E8%B4%9D%E6%9E%84%E9%80%A0%E5%87%BD%E6%95%B0%E4%B8%8E%E8%B5%8B%E5%80%BC) 9 | - [5、获取队首和队尾元素](#5%E8%8E%B7%E5%8F%96%E9%98%9F%E9%A6%96%E5%92%8C%E9%98%9F%E5%B0%BE%E5%85%83%E7%B4%A0) 10 | - [6、queue的大小](#6queue%E7%9A%84%E5%A4%A7%E5%B0%8F) 11 | - [7、使用案例](#7%E4%BD%BF%E7%94%A8%E6%A1%88%E4%BE%8B) 12 | 13 | 14 | 15 | ## STL -- queue 16 | 17 | ### 1、介绍 18 | 19 | * queue是队列容器,是一种“先进先出”的容器。 20 | * queue是简单地装饰deque容器而成为另外的一种容器。 21 | 22 | ### 2、默认构造函数 23 | 24 | queue采用模板类实现,queue对象的默认构造形式: 25 | ```c 26 | queue queT; //尖括号内可以设置指针类型或自定义类型。 27 | queue queInt; //一个存放int的queue容器。 28 | queue queFloat; //一个存放float的queue容器。 29 | queue queString; //一个存放string的queue容器。 30 | ``` 31 | 32 | ### 3、入队和出队操作 33 | 34 | 可使用下面两个函数对queue进行入队和出队操作: 35 | ```c 36 | queue.push(elem); //往队尾添加元素 37 | queue.pop(); //从队头移除第一个元素 38 | ``` 39 | 使用方法: 40 | ```c 41 | queue queInt; 42 | queInt.push(1); 43 | queInt.push(3); 44 | queInt.push(5); 45 | queInt.push(7); 46 | queInt.push(9); 47 | queInt.pop(); 48 | queInt.pop(); 49 | // 此时queInt存放的元素是5,7,9 50 | ``` 51 | ### 4、拷贝构造函数与赋值 52 | 53 | queue提供了拷贝构造函数和重载了“=”运算符来实现拷贝: 54 | ```c 55 | queue(const queue &que); //拷贝构造函数 56 | queue& operator=(const queue &que); //重载等号操作符 57 | ``` 58 | 使用方法: 59 | ```c 60 | queue queIntA; 61 | queIntA.push(1); 62 | queIntA.push(3); 63 | queIntA.push(5); 64 | queIntA.push(7); 65 | queIntA.push(9); 66 | 67 | queue queIntB(queIntA); //拷贝构造 68 | queue queIntC; 69 | queIntC = queIntA; //赋值 70 | ``` 71 | 72 | ### 5、获取队首和队尾元素 73 | 74 | 操作函数如下: 75 | ```c 76 | queue.back(); //返回最后一个元素 77 | queue.front(); //返回第一个元素 78 | ``` 79 | 使用方法: 80 | ```c 81 | queue queIntA; 82 | queIntA.push(1); 83 | queIntA.push(3); 84 | queIntA.push(5); 85 | queIntA.push(7); 86 | queIntA.push(9); 87 | 88 | int iFront = queIntA.front(); //1 89 | int iBack = queIntA.back(); //9 90 | 91 | queIntA.front() = 11; //11 92 | queIntA.back() = 19; //19 93 | ``` 94 | 95 | ### 6、queue的大小 96 | 97 | 相关函数如下: 98 | ```c 99 | queue.empty(); //判断队列是否为空 100 | queue.size(); //返回队列的大小 101 | ``` 102 | 使用方法: 103 | ```c 104 | queue queIntA; 105 | queIntA.push(1); 106 | queIntA.push(3); 107 | queIntA.push(5); 108 | queIntA.push(7); 109 | queIntA.push(9); 110 | 111 | if (!queIntA.empty()) 112 | { 113 | int iSize = queIntA.size(); //5 114 | } 115 | ``` 116 | 117 | ### 7、使用案例 118 | 119 | 详见src下源码。 -------------------------------------------------------------------------------- /03.STL/01.STL使用/queue/src/77.stl_queue.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "queue" 3 | using namespace std; 4 | 5 | class Teacher 6 | { 7 | public: 8 | int age; 9 | char name[32]; 10 | public: 11 | void printT() 12 | { 13 | cout << "age:" << age << endl; 14 | } 15 | }; 16 | 17 | void test1(void) 18 | { 19 | queue qe; 20 | qe.push(1); 21 | qe.push(3); 22 | qe.push(5); 23 | 24 | cout << qe.size() << endl; 25 | while (!qe.empty()) 26 | { 27 | cout << qe.front() << " "; 28 | qe.pop(); 29 | } 30 | cout << endl; 31 | 32 | cout << qe.size() << endl; 33 | } 34 | 35 | void test2(void) 36 | { 37 | queue qe; 38 | 39 | Teacher t1, t2, t3; 40 | t1.age = 10; 41 | t2.age = 20; 42 | t3.age = 30; 43 | qe.push(t1); 44 | qe.push(t2); 45 | qe.push(t3); 46 | 47 | while (!qe.empty()) 48 | { 49 | Teacher temp = qe.front(); 50 | temp.printT(); 51 | qe.pop(); 52 | } 53 | } 54 | 55 | void test3(void) 56 | { 57 | queue qe; 58 | 59 | Teacher t1, t2, t3; 60 | t1.age = 10; 61 | t2.age = 20; 62 | t3.age = 30; 63 | qe.push(&t1); 64 | qe.push(&t2); 65 | qe.push(&t3); 66 | 67 | while (!qe.empty()) 68 | { 69 | Teacher *temp = qe.front(); 70 | temp->printT(); 71 | qe.pop(); 72 | } 73 | } 74 | int main(void) 75 | { 76 | cout << "-------------test1-----------" << endl; 77 | test1(); 78 | cout << "-------------test2-----------" << endl; 79 | test2(); 80 | cout << "-------------test3-----------" << endl; 81 | test3(); 82 | return 0; 83 | } -------------------------------------------------------------------------------- /03.STL/01.STL使用/set/README.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | - [STL -- set和multiset](#stl----set%E5%92%8Cmultiset) 5 | - [1、介绍](#1%E4%BB%8B%E7%BB%8D) 6 | - [2、默认构造函数](#2%E9%BB%98%E8%AE%A4%E6%9E%84%E9%80%A0%E5%87%BD%E6%95%B0) 7 | - [3、迭代器与数据插入](#3%E8%BF%AD%E4%BB%A3%E5%99%A8%E4%B8%8E%E6%95%B0%E6%8D%AE%E6%8F%92%E5%85%A5) 8 | - [4、排序](#4%E6%8E%92%E5%BA%8F) 9 | - [5、拷贝构造与赋值](#5%E6%8B%B7%E8%B4%9D%E6%9E%84%E9%80%A0%E4%B8%8E%E8%B5%8B%E5%80%BC) 10 | - [6、set的大小](#6set%E7%9A%84%E5%A4%A7%E5%B0%8F) 11 | - [7、删除元素](#7%E5%88%A0%E9%99%A4%E5%85%83%E7%B4%A0) 12 | - [8、查找](#8%E6%9F%A5%E6%89%BE) 13 | - [9、使用案例](#9%E4%BD%BF%E7%94%A8%E6%A1%88%E4%BE%8B) 14 | 15 | 16 | 17 | ## STL -- set和multiset 18 | 19 | ### 1、介绍 20 | 21 | * set是一个集合容器,其中所包含的元素是唯一的,集合中的元素按一定的顺序排列。元素插入过程是按排序规则插入,所以不能指定插入位置。 22 | * set采用红黑树变体的数据结构实现,红黑树属于平衡二叉树。在插入操作和删除操作上比vector快。 23 | * set不可以直接存取元素。(不可以使用at.(pos)与[]操作符)。 24 | * multiset与set的区别:set支持唯一键值,每个元素值只能出现一次;而multiset中同一值可以出现多次。 25 | * 不可以直接修改set或multiset容器中的元素值,因为该类容器是自动排序的。如果希望修改一个元素值,必须先删除原有的元素,再插入新的元素。 26 | 27 | ### 2、默认构造函数 28 | 29 | 构造函数示范如下: 30 | ```c 31 | set setInt; //一个存放int的set容器。 32 | set setFloat; //一个存放float的set容器。 33 | set setString; //一个存放string的set容器。 34 | multiset mulsetInt; //一个存放int的multi set容器。 35 | multiset multisetFloat; //一个存放float的multi set容器。 36 | multiset multisetString; //一个存放string的multi set容器。 37 | ``` 38 | 39 | ### 3、迭代器与数据插入 40 | 41 | 相关操作函数示例如下: 42 | ```c 43 | set.insert(elem); //在容器中插入元素。 44 | set.begin(); //返回容器中第一个数据的迭代器。 45 | set.end(); //返回容器中最后一个数据之后的迭代器。 46 | set.rbegin(); //返回容器中倒数第一个元素的迭代器。 47 | set.rend(); //返回容器中倒数最后一个元素的后面的迭代器。 48 | ``` 49 | 50 | 使用方法: 51 | ```c 52 | set setInt; 53 | setInt.insert(3); 54 | setInt.insert(1); 55 | setInt.insert(5); 56 | setInt.insert(2); 57 | for(set::iterator it=setInt.begin(); it!=setInt.end(); ++it) 58 | { 59 | int iItem = *it; 60 | cout << iItem; //或直接使用cout << *it 61 | } 62 | //这样子便顺序输出 1 2 3 5。 63 | ``` 64 | 65 | ### 4、排序 66 | 67 | 相关操作函数如下所示: 68 | ```c 69 | set > setIntA; //该容器是按升序方式排列元素。 70 | set> setIntB; //该容器是按降序方式排列元素。 71 | ``` 72 | set 相当于 set>。less与greater中的int可以改成其它类型,该类型主要要跟set容纳的数据类型一致。 73 | 74 | 使用方法如下: 75 | ```c 76 | set> setIntB; 77 | setIntB.insert(3); 78 | setIntB.insert(1); 79 | setIntB.insert(5); 80 | setIntB.insert(2); 81 | // 此时容器setIntB就包含了按顺序的5,3,2,1元素 82 | ``` 83 | 84 | 那么less<>与greater<>是什么?如果set<>不包含int类型,而是包含自定义类型,set容器如何排序? 85 | 86 | 要解决如上两个问题,需要了解容器的函数对象,也叫仿函数,英文名叫functor。下面将讲解什么是functor,以及functor的用法。 87 | 88 | 尽管函数指针被广泛用于实现函数回调,但C++还提供了一个重要的实现回调函数的方法,那就是函数对象。functor,翻译成函数对象,仿函数,算符,是重载了“()”操作符的普通类对象。从语法上讲,它与普通函数行为类似。greater<>与less<>就是函数对象。下面举出greater的简易实现原理: 89 | 90 | ```c 91 | struct greater 92 | { 93 | bool operator() (const int& iLeft, const int& iRight) 94 | { 95 | return (iLeft>iRight); //如果是实现less的话,这边是写return (iLeft 102 | #include 103 | #include 104 | using namespace std; 105 | 106 | class CStudent 107 | { 108 | public: 109 | CStudent(int iID, string strName) 110 | { 111 | m_iID = iID; 112 | m_strName = strName; 113 | } 114 | int m_iID; //学号 115 | string m_strName; //姓名 116 | }; 117 | 118 | struct StuFunctor 119 | { 120 | bool operator() (const CStudent &stu1, const CStudent &stu2) 121 | { 122 | return (stu1.m_iID setStu; 129 | setStu.insert(CStudent(3, "小张")); 130 | setStu.insert(CStudent(1, "小李")); 131 | setStu.insert(CStudent(5, "小王")); 132 | setStu.insert(CStudent(2, "小刘")); 133 | //此时容器setStu包含了四个学生对象,分别是按姓名顺序的“小李”,“小刘”,“小张”,“小王” 134 | for (set::iterator it = setStu.begin(); it != setStu.end(); it++) 135 | { 136 | cout << it->m_iID << "-" << it->m_strName << endl; 137 | } 138 | 139 | } 140 | ``` 141 | 输出结果如下: 142 | ``` 143 | 1-小李 144 | 2-小刘 145 | 3-小张 146 | 5-小王 147 | ``` 148 | 149 | ### 5、拷贝构造与赋值 150 | 151 | 操作函数如下所示: 152 | ```c 153 | set(const set &st); //拷贝构造函数 154 | set& operator=(const set &st); //重载等号操作符 155 | set.swap(st); //交换两个集合容器 156 | ``` 157 | 使用方法: 158 | ```c 159 | set setIntA; 160 | setIntA.insert(3); 161 | setIntA.insert(1); 162 | setIntA.insert(7); 163 | setIntA.insert(5); 164 | setIntA.insert(9); 165 | 166 | set setIntB(setIntA); //1 3 5 7 9 167 | 168 | set setIntC; 169 | setIntC = setIntA; //1 3 5 7 9 170 | 171 | setIntC.insert(6); 172 | setIntC.swap(setIntA); //交换 173 | ``` 174 | 175 | ### 6、set的大小 176 | 177 | 操作函数如下所示: 178 | ```c 179 | set.size(); //返回容器中元素的数目 180 | set.empty();//判断容器是否为空 181 | ``` 182 | 183 | 使用方法: 184 | ```c 185 | set setIntA; 186 | setIntA.insert(3); 187 | setIntA.insert(1); 188 | setIntA.insert(7); 189 | setIntA.insert(5); 190 | setIntA.insert(9); 191 | 192 | if (!setIntA.empty()) 193 | { 194 | int iSize = setIntA.size(); //5 195 | } 196 | ``` 197 | 198 | ### 7、删除元素 199 | 200 | 操作函数如下所示: 201 | ```c 202 | set.clear(); //清除所有元素 203 | set.erase(pos); //删除pos迭代器所指的元素,返回下一个元素的迭代器。 204 | set.erase(beg,end); //删除区间[beg,end)的所有元素 ,返回下一个元素的迭代器。 205 | set.erase(elem); //删除容器中值为elem的元素。 206 | ``` 207 | 208 | 假设setInt是用set声明的容器,现已包含按顺序的1,3,5,6,9,11元素,现进行如下操作: 209 | ```c 210 | set::iterator itBegin=setInt.begin(); 211 | ++itBegin; 212 | set::iterator itEnd=setInt.begin(); 213 | ++itEnd; 214 | ++itEnd; 215 | ++itEnd; 216 | setInt.erase(itBegin,itEnd);//此时容器setInt包含按顺序的1,6,9,11四个元素。 217 | 218 | // 删除容器中第一个元素 219 | setInt.erase(setInt.begin()); //6,9,11 220 | 221 | // 删除容器中值为9的元素 222 | set.erase(9); 223 | 224 | // 删除setInt的所有元素 225 | setInt.clear(); //容器为空 226 | ``` 227 | 228 | ### 8、查找 229 | 230 | 操作函数如下所示: 231 | ```c 232 | set.find(elem); //查找elem元素,返回指向elem元素的迭代器。 233 | set.count(elem); //返回容器中值为elem的元素个数。对set来说,要么是0,要么是1。对multiset来说,值可能大于1。 234 | set.lower_bound(elem); //返回第一个>=elem元素的迭代器。 235 | set.upper_bound(elem); // 返回第一个>elem元素的迭代器。 236 | set.equal_range(elem); //返回容器中与elem相等的上下限的两个迭代器。上限是闭区间,下限是开区间,如[beg,end),这两个迭代器被封装在pair中。 237 | ``` 238 | 239 | 有必要在这里补充下pair: 240 | 241 | * pair译为对组,可以将两个值视为一个单元。 242 | * pair存放的两个值的类型,可以不一样,如T1为int,T2为float。T1,T2也可以是自定义类型。 243 | * pair.first是pair里面的第一个值,是T1类型。 244 | * pair.second是pair里面的第二个值,是T2类型。 245 | 246 | 使用方法如下: 247 | ```c 248 | #include 249 | #include 250 | #include 251 | using namespace std; 252 | 253 | int main(void) 254 | { 255 | set setInt; 256 | setInt.insert(3); 257 | setInt.insert(1); 258 | setInt.insert(7); 259 | setInt.insert(5); 260 | setInt.insert(9); 261 | 262 | cout << "---------find-----------" << endl; 263 | set::iterator itA = setInt.find(5); 264 | int iA = *itA; //iA == 5 265 | cout << iA << endl; 266 | 267 | cout << "---------count-----------" << endl; 268 | int iCount = setInt.count(5); //iCount == 1 269 | cout << iCount << endl; 270 | 271 | cout << "---------lower/upper_bound-----------" << endl; 272 | set::iterator itB = setInt.lower_bound(5);// >= 5 273 | set::iterator itC = setInt.upper_bound(5);// > 5 274 | int iB = *itB; //iB == 5 275 | int iC = *itC; //iC == 7 276 | cout << iB << "------" << iC << endl; 277 | 278 | cout << "---------equal_range-----------" << endl; 279 | pair< set::iterator, set::iterator > pairIt = setInt.equal_range(5);// [beg, end) 280 | set::iterator itBeg = pairIt.first; 281 | set::iterator itEnd = pairIt.second; 282 | cout << *itBeg << "----" << *itEnd << endl; 283 | 284 | return 0; 285 | } 286 | ``` 287 | 输出: 288 | ``` 289 | ---------find----------- 290 | 5 291 | ---------count----------- 292 | 1 293 | ---------lower/upper_bound----------- 294 | 5------7 295 | ---------equal_range----------- 296 | 5----7 297 | ``` 298 | 299 | ### 9、使用案例 300 | 301 | 详见src下源码。 -------------------------------------------------------------------------------- /03.STL/01.STL使用/set/src/81.stl_set_functor.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hujiese/cpp-study/c94ec4adf61a059e7e768cabc2bcb7b276327bd6/03.STL/01.STL使用/set/src/81.stl_set_functor.cpp -------------------------------------------------------------------------------- /03.STL/01.STL使用/set/src/82.stl_set_find.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | using namespace std; 5 | 6 | int main(void) 7 | { 8 | set setInt; 9 | setInt.insert(3); 10 | setInt.insert(1); 11 | setInt.insert(7); 12 | setInt.insert(5); 13 | setInt.insert(9); 14 | 15 | cout << "---------find-----------" << endl; 16 | set::iterator itA = setInt.find(5); 17 | int iA = *itA; //iA == 5 18 | cout << iA << endl; 19 | 20 | cout << "---------count-----------" << endl; 21 | int iCount = setInt.count(5); //iCount == 1 22 | cout << iCount << endl; 23 | 24 | cout << "---------lower/upper_bound-----------" << endl; 25 | set::iterator itB = setInt.lower_bound(5);// >= 5 26 | set::iterator itC = setInt.upper_bound(5);// > 5 27 | int iB = *itB; //iB == 5 28 | int iC = *itC; //iC == 7 29 | cout << iB << "------" << iC << endl; 30 | 31 | cout << "---------equal_range-----------" << endl; 32 | pair< set::iterator, set::iterator > pairIt = setInt.equal_range(5);// [beg, end) 33 | set::iterator itBeg = pairIt.first; 34 | set::iterator itEnd = pairIt.second; 35 | cout << *itBeg << "----" << *itEnd << endl; 36 | 37 | return 0; 38 | } -------------------------------------------------------------------------------- /03.STL/01.STL使用/set/src/83.stl_set.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hujiese/cpp-study/c94ec4adf61a059e7e768cabc2bcb7b276327bd6/03.STL/01.STL使用/set/src/83.stl_set.cpp -------------------------------------------------------------------------------- /03.STL/01.STL使用/stack/README.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | - [STL -- stack](#stl----stack) 5 | - [1、介绍](#1%E4%BB%8B%E7%BB%8D) 6 | - [2、默认构造函数](#2%E9%BB%98%E8%AE%A4%E6%9E%84%E9%80%A0%E5%87%BD%E6%95%B0) 7 | - [3、出栈和入栈操作](#3%E5%87%BA%E6%A0%88%E5%92%8C%E5%85%A5%E6%A0%88%E6%93%8D%E4%BD%9C) 8 | - [4、获取栈顶元素](#4%E8%8E%B7%E5%8F%96%E6%A0%88%E9%A1%B6%E5%85%83%E7%B4%A0) 9 | - [5、stack的大小](#5stack%E7%9A%84%E5%A4%A7%E5%B0%8F) 10 | - [6、使用案例](#6%E4%BD%BF%E7%94%A8%E6%A1%88%E4%BE%8B) 11 | 12 | 13 | 14 | ## STL -- stack 15 | 16 | ### 1、介绍 17 | 18 | * stack是堆栈容器,是一种“先进后出”的容器。 19 | * stack是简单地装饰deque容器而成为另外的一种容器。 20 | 21 | ### 2、默认构造函数 22 | 23 | stack采用模板类实现, stack对象的默认构造形式: 24 | ```c 25 | stack stkT; //尖括号内可以设置指针类型或自定义类型。 26 | stack stkInt; //一个存放int的stack容器。 27 | stack stkFloat; //一个存放float的stack容器。 28 | stack stkString; //一个存放string的stack容器。 29 | ``` 30 | 31 | ### 3、出栈和入栈操作 32 | 33 | 函数定义如下: 34 | ```c 35 | stack.push(elem); //往栈头添加元素 36 | stack.pop(); //从栈头移除第一个元素 37 | ``` 38 | 使用方法: 39 | ```c 40 | stack stkInt; 41 | stkInt.push(1); 42 | stkInt.push(3); 43 | stkInt.pop(); 44 | stkInt.push(5); 45 | stkInt.push(7); 46 | stkInt.push(9); 47 | stkInt.pop(); 48 | stkInt.pop(); 49 | // 此时stkInt存放的元素是1,5 50 | ``` 51 | ### 4、获取栈顶元素 52 | 53 | 函数定义如下: 54 | ```c 55 | stack.top(); //返回最后一个压入栈元素 56 | ``` 57 | 使用方法: 58 | ```c 59 | stack stkIntA; 60 | stkIntA.push(1); 61 | stkIntA.push(3); 62 | stkIntA.push(5); 63 | stkIntA.push(7); 64 | stkIntA.push(9); 65 | 66 | int iTop = stkIntA.top(); //9 67 | stkIntA.top() = 19; //19 68 | ``` 69 | 70 | ### 5、stack的大小 71 | 72 | 可通过下面这组函数获取栈的大小相关信息: 73 | ```c 74 | stack.empty(); //判断堆栈是否为空 75 | stack.size(); //返回堆栈的大小 76 | ``` 77 | 使用方法: 78 | ```c 79 | stack stkIntA; 80 | stkIntA.push(1); 81 | stkIntA.push(3); 82 | stkIntA.push(5); 83 | stkIntA.push(7); 84 | stkIntA.push(9); 85 | 86 | if (!stkIntA.empty()) 87 | { 88 | int iSize = stkIntA.size(); //5 89 | } 90 | ``` 91 | ### 6、使用案例 92 | 93 | 详见src下源码。 -------------------------------------------------------------------------------- /03.STL/01.STL使用/stack/src/76.stl_stack.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hujiese/cpp-study/c94ec4adf61a059e7e768cabc2bcb7b276327bd6/03.STL/01.STL使用/stack/src/76.stl_stack.cpp -------------------------------------------------------------------------------- /03.STL/01.STL使用/string/README.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | - [STL -- string](#stl----string) 5 | - [1、概念](#1%E6%A6%82%E5%BF%B5) 6 | - [2、构造函数](#2%E6%9E%84%E9%80%A0%E5%87%BD%E6%95%B0) 7 | - [3、存取字符操作](#3%E5%AD%98%E5%8F%96%E5%AD%97%E7%AC%A6%E6%93%8D%E4%BD%9C) 8 | - [4、string 转 const char*](#4string-%E8%BD%AC-const-char) 9 | - [5、把string拷贝到char*指向的内存空间](#5%E6%8A%8Astring%E6%8B%B7%E8%B4%9D%E5%88%B0char%E6%8C%87%E5%90%91%E7%9A%84%E5%86%85%E5%AD%98%E7%A9%BA%E9%97%B4) 10 | - [6、获取string 长度](#6%E8%8E%B7%E5%8F%96string-%E9%95%BF%E5%BA%A6) 11 | - [7、赋值操作](#7%E8%B5%8B%E5%80%BC%E6%93%8D%E4%BD%9C) 12 | - [8、字符串拼接](#8%E5%AD%97%E7%AC%A6%E4%B8%B2%E6%8B%BC%E6%8E%A5) 13 | - [9、字符串比较](#9%E5%AD%97%E7%AC%A6%E4%B8%B2%E6%AF%94%E8%BE%83) 14 | - [10、获取字串](#10%E8%8E%B7%E5%8F%96%E5%AD%97%E4%B8%B2) 15 | - [11、查找 和 替换](#11%E6%9F%A5%E6%89%BE-%E5%92%8C-%E6%9B%BF%E6%8D%A2) 16 | - [12、区间删除和插入](#12%E5%8C%BA%E9%97%B4%E5%88%A0%E9%99%A4%E5%92%8C%E6%8F%92%E5%85%A5) 17 | - [13、算法相关](#13%E7%AE%97%E6%B3%95%E7%9B%B8%E5%85%B3) 18 | - [14、使用案例](#14%E4%BD%BF%E7%94%A8%E6%A1%88%E4%BE%8B) 19 | 20 | 21 | 22 | ## STL -- string 23 | 24 | ### 1、概念 25 | 26 | string是STL的字符串类型,通常用来表示字符串。而在使用string之前,字符串通常是用char*表示的。string与char*都可以用来表示字符串,那么二者有什么区别呢。 27 | 28 | 下面是string和char*的比较: 29 | 30 | * string是一个类, char*是一个指向字符的指针。 31 | * string封装了char*,管理这个字符串,是一个char*型的容器。 32 | * string不用考虑内存释放和越界。 33 | * string管理char*所分配的内存。每一次string的复制,取值都由string类负责维护,不用担心复制越界和取值越界等。 34 | * string提供了一系列的字符串操作函数(这个等下会详讲),例如查找find,拷贝copy,删除erase,替换replace,插入insert。 35 | 36 | ### 2、构造函数 37 | 38 | * 默认构造函数: 39 | ```c 40 | string(); //构造一个空的字符串string s1。 41 | ``` 42 | * 拷贝构造函数: 43 | ```c 44 | string(const string &str); //构造一个与str一样的string。如string s1(s2)。 45 | ``` 46 | * 带参数的构造函数: 47 | ```c 48 | string(const char *s); //用字符串s初始化 49 | string(int n,char c); //用n个字符c初始化 50 | ``` 51 | 52 | ### 3、存取字符操作 53 | 54 | * string类的字符操作: 55 | ```c 56 | const char &operator[] (int n) const; 57 | const char &at(int n) const; 58 | char &operator[] (int n); 59 | char &at(int n); 60 | ``` 61 | 其中operator[]和at()均返回当前字符串中第n个字符,但二者是有区别的。主要区别在于at()在越界时会抛出异常,[]在刚好越界时会返回(char)0,再继续越界时,编译器直接出错。如果你的程序希望可以通过try,catch捕获异常,建议采用at()。 62 | 63 | ### 4、string 转 const char* 64 | ```c 65 | const char *c_str() const; //返回一个以'\0'结尾的字符串的首地址 66 | ``` 67 | 68 | ### 5、把string拷贝到char*指向的内存空间 69 | ```c 70 | int copy(char *s, int n, int pos=0) const; 71 | ``` 72 | 该函数把当前串中以pos开始的n个字符拷贝到以s为起始位置的字符数组中,返回实际拷贝的数目。注意要保证s所指向的空间足够大以容纳当前字符串,不然会越界。 73 | 74 | ### 6、获取string 长度 75 | 76 | ```c 77 | int length() const; //返回当前字符串的长度。长度不包括字符串结尾的'\0'。 78 | bool empty() const; //当前字符串是否为空 79 | ``` 80 | 81 | ### 7、赋值操作 82 | 83 | ```c 84 | string &operator=(const string &s);//把字符串s赋给当前的字符串 85 | string &assign(const char *s); //把字符串s赋给当前的字符串 86 | string &assign(const char *s, int n); //把字符串s的前n个字符赋给当前的字符串 87 | string &assign(const string &s); //把字符串s赋给当前字符串 88 | string &assign(int n,char c); //用n个字符c赋给当前字符串 89 | string &assign(const string &s,int start, int n); //把字符串s中从start开始的n个字符赋给当前字符串 90 | ``` 91 | 92 | ### 8、字符串拼接 93 | ```c 94 | string &operator+=(const string &s); //把字符串s连接到当前字符串结尾 95 | string &operator+=(const char *s);//把字符串s连接到当前字符串结尾 96 | string &append(const char *s); //把字符串s连接到当前字符串结尾 97 | string &append(const char *s,int n); //把字符串s的前n个字符连接到当前字符串结尾 98 | string &append(const string &s); //同operator+=() 99 | string &append(const string &s,int pos, int n);//把字符串s中从pos开始的n个字符连接到当前字符串结尾 100 | string &append(int n, char c); //在当前字符串结尾添加n个字符c 101 | ``` 102 | ### 9、字符串比较 103 | ```c 104 | int compare(const string &s) const; //与字符串s比较 105 | int compare(const char *s) const; //与字符串s比较 106 | ``` 107 | compare函数在>时返回 1,<时返回 -1,==时返回 0。比较区分大小写,比较时参考字典顺序,排越前面的越小。大写的A比小写的a小。 108 | 109 | ### 10、获取字串 110 | 111 | ```c 112 | string substr(int pos=0, int n=npos) const; //返回由pos开始的n个字符组成的子字符串 113 | ``` 114 | 115 | ### 11、查找 和 替换 116 | 117 | * 查找 118 | 119 | ```c 120 | int find(char c,int pos=0) const; //从pos开始查找字符c在当前字符串的位置 121 | int find(const char *s, int pos=0) const; //从pos开始查找字符串s在当前字符串的位置 122 | int find(const string &s, int pos=0) const; //从pos开始查找字符串s在当前字符串中的位置 123 | find函数如果查找不到,就返回-1 124 | int rfind(char c, int pos=npos) const; //从pos开始从后向前查找字符c在当前字符串中的位置 125 | int rfind(const char *s, int pos=npos) const; 126 | int rfind(const string &s, int pos=npos) const; 127 | //rfind是反向查找的意思,如果查找不到, 返回-1 128 | ``` 129 | 130 | * 替换 131 | 132 | ```c 133 | string &replace(int pos, int n, const char *s);//删除从pos开始的n个字符,然后在pos处插入串s 134 | string &replace(int pos, int n, const string &s); //删除从pos开始的n个字符,然后在pos处插入串s 135 | void swap(string &s2); //交换当前字符串与s2的值 136 | ``` 137 | 138 | ### 12、区间删除和插入 139 | 140 | ```c 141 | string &insert(int pos, const char *s); 142 | string &insert(int pos, const string &s); 143 | //前两个函数在pos位置插入字符串s 144 | string &insert(int pos, int n, char c); //在pos位置 插入n个字符c 145 | string &erase(int pos=0, int n=npos); //删除pos开始的n个字符,返回修改后的字符串 146 | ``` 147 | 148 | ### 13、算法相关 149 | 150 | ```c 151 | string s2 = "AAAbbb"; 152 | transform(s2.begin(), s2.end(), s2.begin(), toupper); 153 | cout << s2 << endl; 154 | 155 | string s3 = "AAAbbb"; 156 | transform(s3.begin(), s3.end(), s3.begin(), tolower); 157 | cout << s3 << endl; 158 | ``` 159 | 160 | ### 14、使用案例 161 | 162 | 详见src下源码。 -------------------------------------------------------------------------------- /03.STL/01.STL使用/string/src/72.stl_string.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hujiese/cpp-study/c94ec4adf61a059e7e768cabc2bcb7b276327bd6/03.STL/01.STL使用/string/src/72.stl_string.cpp -------------------------------------------------------------------------------- /03.STL/01.STL使用/string/src/78.stl_string2.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hujiese/cpp-study/c94ec4adf61a059e7e768cabc2bcb7b276327bd6/03.STL/01.STL使用/string/src/78.stl_string2.cpp -------------------------------------------------------------------------------- /03.STL/01.STL使用/vector/README.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | - [STL -- vector](#stl----vector) 5 | - [1、介绍](#1%E4%BB%8B%E7%BB%8D) 6 | - [2、默认构造函数](#2%E9%BB%98%E8%AE%A4%E6%9E%84%E9%80%A0%E5%87%BD%E6%95%B0) 7 | - [3、带参数构造函数](#3%E5%B8%A6%E5%8F%82%E6%95%B0%E6%9E%84%E9%80%A0%E5%87%BD%E6%95%B0) 8 | - [4、赋值方法](#4%E8%B5%8B%E5%80%BC%E6%96%B9%E6%B3%95) 9 | - [5、vector大小](#5vector%E5%A4%A7%E5%B0%8F) 10 | - [6、vector末尾添加移除操作](#6vector%E6%9C%AB%E5%B0%BE%E6%B7%BB%E5%8A%A0%E7%A7%BB%E9%99%A4%E6%93%8D%E4%BD%9C) 11 | - [7、vector数据存取](#7vector%E6%95%B0%E6%8D%AE%E5%AD%98%E5%8F%96) 12 | - [8、迭代器基本原理](#8%E8%BF%AD%E4%BB%A3%E5%99%A8%E5%9F%BA%E6%9C%AC%E5%8E%9F%E7%90%86) 13 | - [9、vector与迭代器](#9vector%E4%B8%8E%E8%BF%AD%E4%BB%A3%E5%99%A8) 14 | - [10、vector的插入](#10vector%E7%9A%84%E6%8F%92%E5%85%A5) 15 | - [11、vector的删除](#11vector%E7%9A%84%E5%88%A0%E9%99%A4) 16 | - [12、使用案例](#12%E4%BD%BF%E7%94%A8%E6%A1%88%E4%BE%8B) 17 | 18 | 19 | 20 | ## STL -- vector 21 | 22 | ### 1、介绍 23 | 24 | * vector是将元素置于一个动态数组中加以管理的容器。 25 | * vector可以随机存取元素(支持索引值直接存取, 用[]操作符或at()方法,这个等下会详讲)。 26 | * vector尾部添加或移除元素非常快速。但是在中部或头部插入元素或移除元素比较费时。 27 | 28 | ### 2、默认构造函数 29 | 30 | vector采用模板类实现,vector对象的默认构造形式: 31 | ```c 32 | vector vecT; 33 | ``` 34 | 使用方法: 35 | ```c 36 | vector vecInt; //一个存放int的vector容器。 37 | vector vecFloat; //一个存放float的vector容器。 38 | vector vecString; //一个存放string的vector容器。 39 | ... //尖括号内还可以设置指针类型或自定义类型。 40 | Class CA{}; 41 | vector vecpCA; //用于存放CA对象的指针的vector容器。 42 | vector vecCA; //用于存放CA对象的vector容器。由于容器元素的存放是按值复制的方式进行的,所以此时CA必须提供CA的拷贝构造函数,以保证CA对象间拷贝正常。 43 | ``` 44 | 45 | ### 3、带参数构造函数 46 | 47 | 带参构造函数定义如下: 48 | ```c 49 | vector(beg,end); //构造函数将[beg, end)区间中的元素拷贝给本身。注意该区间是左闭右开的区间。 50 | vector(n,elem); //构造函数将n个elem拷贝给本身。 51 | vector(const vector &vec); //拷贝构造函数 52 | ``` 53 | 54 | 使用方法: 55 | ```c 56 | int iArray[] = {0,1,2,3,4}; 57 | vector vecIntA( iArray, iArray+5 ); 58 | 59 | vector vecIntB ( vecIntA.begin() , vecIntA.end() ); //用构造函数初始化容器vecIntB 60 | vector vecIntB ( vecIntA.begin() , vecIntA.begin()+3 ); 61 | vector vecIntC(3,9); //此代码运行后,容器vecIntB就存放3个元素,每个元素的值是9。 62 | 63 | vector vecIntD(vecIntA); 64 | ``` 65 | 66 | ### 4、赋值方法 67 | 68 | 可通过如下几种方式对vector进行赋值: 69 | ```c 70 | vector.assign(beg,end); //将[beg, end)区间中的数据拷贝赋值给本身。注意该区间是左闭右开的区间。 71 | vector.assign(n,elem); //将n个elem拷贝赋值给本身。 72 | vector& operator=(const vector &vec); //重载等号操作符 73 | vector.swap(vec); // 将vec与本身的元素互换。 74 | ``` 75 | 76 | 使用方法: 77 | ```c 78 | vector vecIntA, vecIntB, vecIntC, vecIntD; 79 | int iArray[] = {0,1,2,3,4}; 80 | vecIntA.assign(iArray,iArray+5); 81 | 82 | vecIntB.assign( vecIntA.begin(), vecIntA.end() ); //用其它容器的迭代器作参数。 83 | 84 | vecIntC.assign(3,9); 85 | 86 | vector vecIntD; 87 | vecIntD = vecIntA; 88 | 89 | vecIntA.swap(vecIntD); 90 | ``` 91 | 92 | ### 5、vector大小 93 | 94 | 可通过下面这些函数来获取一个vector对象的容量和大小,或者改变vector对象容量: 95 | ```c 96 | vector.size(); //返回容器中元素的个数 97 | vector.empty(); //判断容器是否为空 98 | vector.resize(num); //重新指定容器的长度为num,若容器变长,则以默认值填充新位置。如果容器变短,则末尾超出容器长度的元素被删除。 99 | vector.resize(num, elem); //重新指定容器的长度为num,若容器变长,则以elem值填充新位置。如果容器变短,则末尾超出容器长度的元素被删除。 100 | ``` 101 | 102 | 假设vecInt是vector 声明的容器,现已包含1,2,3元素,下面对vecInt进行一系列操作: 103 | ```c 104 | int iSize = vecInt.size(); //iSize == 3; 105 | bool bEmpty = vecInt.empty(); // bEmpty == false; 106 | vecInt.resize(5); //此时里面包含1,2,3,0,0元素。 107 | vecInt.resize(8,3); //此时里面包含1,2,3,0,0,3,3,3元素。 108 | vecInt.resize(2); //此时里面包含1,2元素。 109 | ``` 110 | 111 | ### 6、vector末尾添加移除操作 112 | 113 | 案例如下: 114 | ```c 115 | vector vecInt; 116 | vecInt.push_back(1); //在容器尾部加入一个元素 117 | vecInt.push_back(3); //移除容器中最后一个元素 118 | vecInt.push_back(5); 119 | vecInt.push_back(7); 120 | vecInt.push_back(9); 121 | vecInt.pop_back(); 122 | vecInt.pop_back(); 123 | //{5 ,7 ,9} 124 | ``` 125 | 126 | ### 7、vector数据存取 127 | 128 | 可通过下面两种方式获取vector对象某个索引位置的值: 129 | ```c 130 | vec.at(idx); //返回索引idx所指的数据,如果idx越界,抛出out_of_range异常。 131 | vec[idx]; //返回索引idx所指的数据,越界时,运行直接报错 132 | ``` 133 | 134 | 使用方法: 135 | ```c 136 | vector vecInt; //假设包含1 ,3 ,5 ,7 ,9 137 | vecInt.at(2) == vecInt[2] ; //5 138 | vecInt.at(2) = 8; // 或 vecInt[2] = 8; 139 | // vecInt 就包含 1, 3, 8, 7, 9值 140 | 141 | int iF = vector.front(); //iF==1 142 | int iB = vector.back(); //iB==9 143 | vector.front() = 11; //vecInt包含{11,3,8,7,9} 144 | vector.back() = 19; //vecInt包含{11,3,8,7,19} 145 | ``` 146 | 147 | ### 8、迭代器基本原理 148 | 149 | * 迭代器是一个“可遍历STL容器内全部或部分元素”的对象。 150 | * 迭代器指出容器中的一个特定位置。 151 | * 迭代器就如同一个指针。 152 | * 迭代器提供对一个容器中的对象的访问方法,并且可以定义了容器中对象的范围。 153 | 154 | 下面大概介绍一下迭代器的类别: 155 | 156 | * 输入迭代器:也有叫法称之为“只读迭代器”,它从容器中读取元素,只能一次读入一个元素向前移动,只支持一遍算法,同一个输入迭代器不能两遍遍历一个序列。 157 | * 输出迭代器:也有叫法称之为“只写迭代器”,它往容器中写入元素,只能一次写入一个元素向前移动,只支持一遍算法,同一个输出迭代器不能两遍遍历一个序列。 158 | * 正向迭代器:组合输入迭代器和输出迭代器的功能,还可以多次解析一个迭代器指定的位置,可以对一个值进行多次读/写。 159 | * 双向迭代器:组合正向迭代器的功能,还可以通过--操作符向后移动位置。 160 | * 随机访问迭代器:组合双向迭代器的功能,还可以向前向后跳过任意个位置,可以直接访问容器中任何位置的元素。 161 | 162 | ### 9、vector与迭代器 163 | 164 | ![](./img/iterator.png) 165 | 166 | ```c 167 | vector vecInt; //假设包含1,3,5,7,9元素 168 | vector::iterator it; //声明容器vector的迭代器。 169 | it = vecInt.begin(); // *it == 1 170 | ++it; //或者it++; *it == 3 ,前++的效率比后++的效率高,前++返回引用,后++返回值。 171 | it += 2; //*it == 7 172 | it = it+1; //*it == 9 173 | ++it; // it == vecInt.end(); 此时不能再执行*it,会出错! 174 | ``` 175 | 176 | 正向遍历: 177 | ```c 178 | // 打印出1 3 5 7 9 179 | for(vector::iterator it=vecInt.begin(); it!=vecInt.end(); ++it) 180 | { 181 | int iItem = *it; 182 | cout << iItem; //或直接使用 cout << *it; 183 | } 184 | ``` 185 | 186 | 逆向遍历: 187 | ```c 188 | // 此时将打印出9,7,5,3,1 189 | for(vector::reverse_iterator rit=vecInt.rbegin(); rit!=vecInt.rend(); ++rit) //注意,小括号内仍是++rit 190 | { 191 | int iItem = *rit; 192 | cout << iItem; //或直接使用cout << *rit; 193 | } 194 | ``` 195 | 需要注意的是,这里迭代器的声明采用vector::reverse_iterator,而非vector::iterator。 196 | 197 | 迭代器还有其它两种声明方法:vector::const_iterator 与 vector::const_reverse_iterator。 198 | 199 | 以上两种分别是vector::iterator 与vector::reverse_iterator 的只读形式,使用这两种迭代器时,不会修改到容器中的值。不过容器中的insert和erase方法仅接受这四种类型中的iterator,其它三种不支持。《Effective STL》建议我们尽量使用iterator取代const_iterator、reverse_iterator和const_reverse_iterator。 200 | 201 | ### 10、vector的插入 202 | 203 | 插入函数有如下几种: 204 | ```c 205 | vector.insert(pos,elem); //在pos位置插入一个elem元素的拷贝,返回新数据的位置。 206 | vector.insert(pos,n,elem); //在pos位置插入n个elem数据,无返回值。 207 | vector.insert(pos,beg,end); //在pos位置插入[beg,end)区间的数据,无返回值 208 | ``` 209 | 210 | 使用案例: 211 | ```c 212 | vector vecA; 213 | vector vecB; 214 | 215 | vecA.push_back(1); 216 | vecA.push_back(3); 217 | vecA.push_back(5); 218 | vecA.push_back(7); 219 | vecA.push_back(9); 220 | 221 | vecB.push_back(2); 222 | vecB.push_back(4); 223 | vecB.push_back(6); 224 | vecB.push_back(8); 225 | 226 | vecA.insert(vecA.begin(), 11); //{11, 1, 3, 5, 7, 9} 227 | vecA.insert(vecA.begin()+1,2,33); //{11,33,33,1,3,5,7,9} 228 | vecA.insert(vecA.begin() , vecB.begin() , vecB.end() ); //{2,4,6,8,11,33,33,1,3,5,7,9} 229 | ``` 230 | 231 | ### 11、vector的删除 232 | 233 | 可使用下面三组函数对vector对象的某些元素进行删除操作: 234 | ```c 235 | vector.clear(); //移除容器的所有数据 236 | vec.erase(beg,end); //删除[beg,end)区间的数据,返回下一个数据的位置。 237 | vec.erase(pos); //删除pos位置的数据,返回下一个数据的位置。 238 | ``` 239 | 240 | 假设vecInt是用vector声明的容器,现已包含按顺序的1,3,5,6,9元素,然后精选下面操作: 241 | ``` 242 | vector::iterator itBegin=vecInt.begin()+1; 243 | vector::iterator itEnd=vecInt.begin()+2; 244 | vecInt.erase(itBegin,itEnd); 245 | //此时容器vecInt包含按顺序的1,6,9三个元素。 246 | ``` 247 | 248 | 再假设 vecInt 包含1,3,2,3,3,3,4,3,5,3,现在要删除容器中等于3的元素: 249 | ```c 250 | for(vector::iterator it=vecInt.being(); it!=vecInt.end(); )//小括号里不需写 ++it 251 | { 252 | if(*it == 3) 253 | { 254 | it = vecInt.erase(it); //以迭代器为参数,删除元素3,并把数据删除后的下一个元素位置返回给迭代器。 255 | //此时,不执行 ++it; 256 | } 257 | else 258 | { 259 | ++it; 260 | } 261 | } 262 | ``` 263 | 264 | 下面这个操作将删除vecInt的所有元素: 265 | ```c 266 | vecInt.clear(); //容器为空 267 | ``` 268 | 269 | ### 12、使用案例 270 | 271 | 具体使用案例详见src下源码。 272 | -------------------------------------------------------------------------------- /03.STL/01.STL使用/vector/img/iterator.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hujiese/cpp-study/c94ec4adf61a059e7e768cabc2bcb7b276327bd6/03.STL/01.STL使用/vector/img/iterator.png -------------------------------------------------------------------------------- /03.STL/01.STL使用/vector/src/73.stl_vector1.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hujiese/cpp-study/c94ec4adf61a059e7e768cabc2bcb7b276327bd6/03.STL/01.STL使用/vector/src/73.stl_vector1.cpp -------------------------------------------------------------------------------- /03.STL/01.STL使用/vector/src/74.stl_vector2.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hujiese/cpp-study/c94ec4adf61a059e7e768cabc2bcb7b276327bd6/03.STL/01.STL使用/vector/src/74.stl_vector2.cpp -------------------------------------------------------------------------------- /03.STL/02.STL原理/img/accumulate.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hujiese/cpp-study/c94ec4adf61a059e7e768cabc2bcb7b276327bd6/03.STL/02.STL原理/img/accumulate.png -------------------------------------------------------------------------------- /03.STL/02.STL原理/img/adapter.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hujiese/cpp-study/c94ec4adf61a059e7e768cabc2bcb7b276327bd6/03.STL/02.STL原理/img/adapter.png -------------------------------------------------------------------------------- /03.STL/02.STL原理/img/adaptor.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hujiese/cpp-study/c94ec4adf61a059e7e768cabc2bcb7b276327bd6/03.STL/02.STL原理/img/adaptor.png -------------------------------------------------------------------------------- /03.STL/02.STL原理/img/algo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hujiese/cpp-study/c94ec4adf61a059e7e768cabc2bcb7b276327bd6/03.STL/02.STL原理/img/algo.png -------------------------------------------------------------------------------- /03.STL/02.STL原理/img/algo10.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hujiese/cpp-study/c94ec4adf61a059e7e768cabc2bcb7b276327bd6/03.STL/02.STL原理/img/algo10.png -------------------------------------------------------------------------------- /03.STL/02.STL原理/img/algo11.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hujiese/cpp-study/c94ec4adf61a059e7e768cabc2bcb7b276327bd6/03.STL/02.STL原理/img/algo11.png -------------------------------------------------------------------------------- /03.STL/02.STL原理/img/algo12.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hujiese/cpp-study/c94ec4adf61a059e7e768cabc2bcb7b276327bd6/03.STL/02.STL原理/img/algo12.png -------------------------------------------------------------------------------- /03.STL/02.STL原理/img/algo2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hujiese/cpp-study/c94ec4adf61a059e7e768cabc2bcb7b276327bd6/03.STL/02.STL原理/img/algo2.png -------------------------------------------------------------------------------- /03.STL/02.STL原理/img/algo3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hujiese/cpp-study/c94ec4adf61a059e7e768cabc2bcb7b276327bd6/03.STL/02.STL原理/img/algo3.png -------------------------------------------------------------------------------- /03.STL/02.STL原理/img/algo4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hujiese/cpp-study/c94ec4adf61a059e7e768cabc2bcb7b276327bd6/03.STL/02.STL原理/img/algo4.png -------------------------------------------------------------------------------- /03.STL/02.STL原理/img/algo5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hujiese/cpp-study/c94ec4adf61a059e7e768cabc2bcb7b276327bd6/03.STL/02.STL原理/img/algo5.png -------------------------------------------------------------------------------- /03.STL/02.STL原理/img/algo6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hujiese/cpp-study/c94ec4adf61a059e7e768cabc2bcb7b276327bd6/03.STL/02.STL原理/img/algo6.png -------------------------------------------------------------------------------- /03.STL/02.STL原理/img/algo7.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hujiese/cpp-study/c94ec4adf61a059e7e768cabc2bcb7b276327bd6/03.STL/02.STL原理/img/algo7.png -------------------------------------------------------------------------------- /03.STL/02.STL原理/img/algo8.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hujiese/cpp-study/c94ec4adf61a059e7e768cabc2bcb7b276327bd6/03.STL/02.STL原理/img/algo8.png -------------------------------------------------------------------------------- /03.STL/02.STL原理/img/algo9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hujiese/cpp-study/c94ec4adf61a059e7e768cabc2bcb7b276327bd6/03.STL/02.STL原理/img/algo9.png -------------------------------------------------------------------------------- /03.STL/02.STL原理/img/allocator.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hujiese/cpp-study/c94ec4adf61a059e7e768cabc2bcb7b276327bd6/03.STL/02.STL原理/img/allocator.png -------------------------------------------------------------------------------- /03.STL/02.STL原理/img/allocator10.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hujiese/cpp-study/c94ec4adf61a059e7e768cabc2bcb7b276327bd6/03.STL/02.STL原理/img/allocator10.png -------------------------------------------------------------------------------- /03.STL/02.STL原理/img/allocator2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hujiese/cpp-study/c94ec4adf61a059e7e768cabc2bcb7b276327bd6/03.STL/02.STL原理/img/allocator2.png -------------------------------------------------------------------------------- /03.STL/02.STL原理/img/allocator3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hujiese/cpp-study/c94ec4adf61a059e7e768cabc2bcb7b276327bd6/03.STL/02.STL原理/img/allocator3.png -------------------------------------------------------------------------------- /03.STL/02.STL原理/img/allocator4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hujiese/cpp-study/c94ec4adf61a059e7e768cabc2bcb7b276327bd6/03.STL/02.STL原理/img/allocator4.png -------------------------------------------------------------------------------- /03.STL/02.STL原理/img/allocator5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hujiese/cpp-study/c94ec4adf61a059e7e768cabc2bcb7b276327bd6/03.STL/02.STL原理/img/allocator5.png -------------------------------------------------------------------------------- /03.STL/02.STL原理/img/allocator6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hujiese/cpp-study/c94ec4adf61a059e7e768cabc2bcb7b276327bd6/03.STL/02.STL原理/img/allocator6.png -------------------------------------------------------------------------------- /03.STL/02.STL原理/img/allocator7.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hujiese/cpp-study/c94ec4adf61a059e7e768cabc2bcb7b276327bd6/03.STL/02.STL原理/img/allocator7.png -------------------------------------------------------------------------------- /03.STL/02.STL原理/img/allocator8.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hujiese/cpp-study/c94ec4adf61a059e7e768cabc2bcb7b276327bd6/03.STL/02.STL原理/img/allocator8.png -------------------------------------------------------------------------------- /03.STL/02.STL原理/img/allocator9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hujiese/cpp-study/c94ec4adf61a059e7e768cabc2bcb7b276327bd6/03.STL/02.STL原理/img/allocator9.png -------------------------------------------------------------------------------- /03.STL/02.STL原理/img/alog9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hujiese/cpp-study/c94ec4adf61a059e7e768cabc2bcb7b276327bd6/03.STL/02.STL原理/img/alog9.png -------------------------------------------------------------------------------- /03.STL/02.STL原理/img/array.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hujiese/cpp-study/c94ec4adf61a059e7e768cabc2bcb7b276327bd6/03.STL/02.STL原理/img/array.png -------------------------------------------------------------------------------- /03.STL/02.STL原理/img/array2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hujiese/cpp-study/c94ec4adf61a059e7e768cabc2bcb7b276327bd6/03.STL/02.STL原理/img/array2.png -------------------------------------------------------------------------------- /03.STL/02.STL原理/img/array3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hujiese/cpp-study/c94ec4adf61a059e7e768cabc2bcb7b276327bd6/03.STL/02.STL原理/img/array3.png -------------------------------------------------------------------------------- /03.STL/02.STL原理/img/binary_search.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hujiese/cpp-study/c94ec4adf61a059e7e768cabc2bcb7b276327bd6/03.STL/02.STL原理/img/binary_search.png -------------------------------------------------------------------------------- /03.STL/02.STL原理/img/bind2nd.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hujiese/cpp-study/c94ec4adf61a059e7e768cabc2bcb7b276327bd6/03.STL/02.STL原理/img/bind2nd.png -------------------------------------------------------------------------------- /03.STL/02.STL原理/img/count.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hujiese/cpp-study/c94ec4adf61a059e7e768cabc2bcb7b276327bd6/03.STL/02.STL原理/img/count.png -------------------------------------------------------------------------------- /03.STL/02.STL原理/img/deque.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hujiese/cpp-study/c94ec4adf61a059e7e768cabc2bcb7b276327bd6/03.STL/02.STL原理/img/deque.png -------------------------------------------------------------------------------- /03.STL/02.STL原理/img/deque10.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hujiese/cpp-study/c94ec4adf61a059e7e768cabc2bcb7b276327bd6/03.STL/02.STL原理/img/deque10.png -------------------------------------------------------------------------------- /03.STL/02.STL原理/img/deque11.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hujiese/cpp-study/c94ec4adf61a059e7e768cabc2bcb7b276327bd6/03.STL/02.STL原理/img/deque11.png -------------------------------------------------------------------------------- /03.STL/02.STL原理/img/deque2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hujiese/cpp-study/c94ec4adf61a059e7e768cabc2bcb7b276327bd6/03.STL/02.STL原理/img/deque2.png -------------------------------------------------------------------------------- /03.STL/02.STL原理/img/deque3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hujiese/cpp-study/c94ec4adf61a059e7e768cabc2bcb7b276327bd6/03.STL/02.STL原理/img/deque3.png -------------------------------------------------------------------------------- /03.STL/02.STL原理/img/deque4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hujiese/cpp-study/c94ec4adf61a059e7e768cabc2bcb7b276327bd6/03.STL/02.STL原理/img/deque4.png -------------------------------------------------------------------------------- /03.STL/02.STL原理/img/deque5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hujiese/cpp-study/c94ec4adf61a059e7e768cabc2bcb7b276327bd6/03.STL/02.STL原理/img/deque5.png -------------------------------------------------------------------------------- /03.STL/02.STL原理/img/deque6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hujiese/cpp-study/c94ec4adf61a059e7e768cabc2bcb7b276327bd6/03.STL/02.STL原理/img/deque6.png -------------------------------------------------------------------------------- /03.STL/02.STL原理/img/deque7.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hujiese/cpp-study/c94ec4adf61a059e7e768cabc2bcb7b276327bd6/03.STL/02.STL原理/img/deque7.png -------------------------------------------------------------------------------- /03.STL/02.STL原理/img/deque8.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hujiese/cpp-study/c94ec4adf61a059e7e768cabc2bcb7b276327bd6/03.STL/02.STL原理/img/deque8.png -------------------------------------------------------------------------------- /03.STL/02.STL原理/img/deque9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hujiese/cpp-study/c94ec4adf61a059e7e768cabc2bcb7b276327bd6/03.STL/02.STL原理/img/deque9.png -------------------------------------------------------------------------------- /03.STL/02.STL原理/img/find.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hujiese/cpp-study/c94ec4adf61a059e7e768cabc2bcb7b276327bd6/03.STL/02.STL原理/img/find.png -------------------------------------------------------------------------------- /03.STL/02.STL原理/img/fl.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hujiese/cpp-study/c94ec4adf61a059e7e768cabc2bcb7b276327bd6/03.STL/02.STL原理/img/fl.png -------------------------------------------------------------------------------- /03.STL/02.STL原理/img/for_each.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hujiese/cpp-study/c94ec4adf61a059e7e768cabc2bcb7b276327bd6/03.STL/02.STL原理/img/for_each.png -------------------------------------------------------------------------------- /03.STL/02.STL原理/img/forward_list.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hujiese/cpp-study/c94ec4adf61a059e7e768cabc2bcb7b276327bd6/03.STL/02.STL原理/img/forward_list.png -------------------------------------------------------------------------------- /03.STL/02.STL原理/img/func1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hujiese/cpp-study/c94ec4adf61a059e7e768cabc2bcb7b276327bd6/03.STL/02.STL原理/img/func1.png -------------------------------------------------------------------------------- /03.STL/02.STL原理/img/func2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hujiese/cpp-study/c94ec4adf61a059e7e768cabc2bcb7b276327bd6/03.STL/02.STL原理/img/func2.png -------------------------------------------------------------------------------- /03.STL/02.STL原理/img/func3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hujiese/cpp-study/c94ec4adf61a059e7e768cabc2bcb7b276327bd6/03.STL/02.STL原理/img/func3.png -------------------------------------------------------------------------------- /03.STL/02.STL原理/img/func4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hujiese/cpp-study/c94ec4adf61a059e7e768cabc2bcb7b276327bd6/03.STL/02.STL原理/img/func4.png -------------------------------------------------------------------------------- /03.STL/02.STL原理/img/iterator1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hujiese/cpp-study/c94ec4adf61a059e7e768cabc2bcb7b276327bd6/03.STL/02.STL原理/img/iterator1.png -------------------------------------------------------------------------------- /03.STL/02.STL原理/img/iterator10.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hujiese/cpp-study/c94ec4adf61a059e7e768cabc2bcb7b276327bd6/03.STL/02.STL原理/img/iterator10.png -------------------------------------------------------------------------------- /03.STL/02.STL原理/img/iterator11.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hujiese/cpp-study/c94ec4adf61a059e7e768cabc2bcb7b276327bd6/03.STL/02.STL原理/img/iterator11.png -------------------------------------------------------------------------------- /03.STL/02.STL原理/img/iterator12.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hujiese/cpp-study/c94ec4adf61a059e7e768cabc2bcb7b276327bd6/03.STL/02.STL原理/img/iterator12.png -------------------------------------------------------------------------------- /03.STL/02.STL原理/img/iterator2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hujiese/cpp-study/c94ec4adf61a059e7e768cabc2bcb7b276327bd6/03.STL/02.STL原理/img/iterator2.png -------------------------------------------------------------------------------- /03.STL/02.STL原理/img/iterator3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hujiese/cpp-study/c94ec4adf61a059e7e768cabc2bcb7b276327bd6/03.STL/02.STL原理/img/iterator3.png -------------------------------------------------------------------------------- /03.STL/02.STL原理/img/iterator4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hujiese/cpp-study/c94ec4adf61a059e7e768cabc2bcb7b276327bd6/03.STL/02.STL原理/img/iterator4.png -------------------------------------------------------------------------------- /03.STL/02.STL原理/img/iterator5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hujiese/cpp-study/c94ec4adf61a059e7e768cabc2bcb7b276327bd6/03.STL/02.STL原理/img/iterator5.png -------------------------------------------------------------------------------- /03.STL/02.STL原理/img/iterator6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hujiese/cpp-study/c94ec4adf61a059e7e768cabc2bcb7b276327bd6/03.STL/02.STL原理/img/iterator6.png -------------------------------------------------------------------------------- /03.STL/02.STL原理/img/iterator7.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hujiese/cpp-study/c94ec4adf61a059e7e768cabc2bcb7b276327bd6/03.STL/02.STL原理/img/iterator7.png -------------------------------------------------------------------------------- /03.STL/02.STL原理/img/iterator8.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hujiese/cpp-study/c94ec4adf61a059e7e768cabc2bcb7b276327bd6/03.STL/02.STL原理/img/iterator8.png -------------------------------------------------------------------------------- /03.STL/02.STL原理/img/iterator9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hujiese/cpp-study/c94ec4adf61a059e7e768cabc2bcb7b276327bd6/03.STL/02.STL原理/img/iterator9.png -------------------------------------------------------------------------------- /03.STL/02.STL原理/img/list.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hujiese/cpp-study/c94ec4adf61a059e7e768cabc2bcb7b276327bd6/03.STL/02.STL原理/img/list.png -------------------------------------------------------------------------------- /03.STL/02.STL原理/img/map.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hujiese/cpp-study/c94ec4adf61a059e7e768cabc2bcb7b276327bd6/03.STL/02.STL原理/img/map.png -------------------------------------------------------------------------------- /03.STL/02.STL原理/img/multimap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hujiese/cpp-study/c94ec4adf61a059e7e768cabc2bcb7b276327bd6/03.STL/02.STL原理/img/multimap.png -------------------------------------------------------------------------------- /03.STL/02.STL原理/img/multiset.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hujiese/cpp-study/c94ec4adf61a059e7e768cabc2bcb7b276327bd6/03.STL/02.STL原理/img/multiset.png -------------------------------------------------------------------------------- /03.STL/02.STL原理/img/new.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hujiese/cpp-study/c94ec4adf61a059e7e768cabc2bcb7b276327bd6/03.STL/02.STL原理/img/new.png -------------------------------------------------------------------------------- /03.STL/02.STL原理/img/not1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hujiese/cpp-study/c94ec4adf61a059e7e768cabc2bcb7b276327bd6/03.STL/02.STL原理/img/not1.png -------------------------------------------------------------------------------- /03.STL/02.STL原理/img/queue.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hujiese/cpp-study/c94ec4adf61a059e7e768cabc2bcb7b276327bd6/03.STL/02.STL原理/img/queue.png -------------------------------------------------------------------------------- /03.STL/02.STL原理/img/queue2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hujiese/cpp-study/c94ec4adf61a059e7e768cabc2bcb7b276327bd6/03.STL/02.STL原理/img/queue2.png -------------------------------------------------------------------------------- /03.STL/02.STL原理/img/replace.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hujiese/cpp-study/c94ec4adf61a059e7e768cabc2bcb7b276327bd6/03.STL/02.STL原理/img/replace.png -------------------------------------------------------------------------------- /03.STL/02.STL原理/img/set.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hujiese/cpp-study/c94ec4adf61a059e7e768cabc2bcb7b276327bd6/03.STL/02.STL原理/img/set.png -------------------------------------------------------------------------------- /03.STL/02.STL原理/img/sort.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hujiese/cpp-study/c94ec4adf61a059e7e768cabc2bcb7b276327bd6/03.STL/02.STL原理/img/sort.png -------------------------------------------------------------------------------- /03.STL/02.STL原理/img/sort2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hujiese/cpp-study/c94ec4adf61a059e7e768cabc2bcb7b276327bd6/03.STL/02.STL原理/img/sort2.png -------------------------------------------------------------------------------- /03.STL/02.STL原理/img/sq.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hujiese/cpp-study/c94ec4adf61a059e7e768cabc2bcb7b276327bd6/03.STL/02.STL原理/img/sq.png -------------------------------------------------------------------------------- /03.STL/02.STL原理/img/sq2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hujiese/cpp-study/c94ec4adf61a059e7e768cabc2bcb7b276327bd6/03.STL/02.STL原理/img/sq2.png -------------------------------------------------------------------------------- /03.STL/02.STL原理/img/sq3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hujiese/cpp-study/c94ec4adf61a059e7e768cabc2bcb7b276327bd6/03.STL/02.STL原理/img/sq3.png -------------------------------------------------------------------------------- /03.STL/02.STL原理/img/stack.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hujiese/cpp-study/c94ec4adf61a059e7e768cabc2bcb7b276327bd6/03.STL/02.STL原理/img/stack.png -------------------------------------------------------------------------------- /03.STL/02.STL原理/img/stack2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hujiese/cpp-study/c94ec4adf61a059e7e768cabc2bcb7b276327bd6/03.STL/02.STL原理/img/stack2.png -------------------------------------------------------------------------------- /03.STL/02.STL原理/img/stl1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hujiese/cpp-study/c94ec4adf61a059e7e768cabc2bcb7b276327bd6/03.STL/02.STL原理/img/stl1.png -------------------------------------------------------------------------------- /03.STL/02.STL原理/img/stl2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hujiese/cpp-study/c94ec4adf61a059e7e768cabc2bcb7b276327bd6/03.STL/02.STL原理/img/stl2.png -------------------------------------------------------------------------------- /03.STL/02.STL原理/img/stl3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hujiese/cpp-study/c94ec4adf61a059e7e768cabc2bcb7b276327bd6/03.STL/02.STL原理/img/stl3.png -------------------------------------------------------------------------------- /03.STL/02.STL原理/img/traits.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hujiese/cpp-study/c94ec4adf61a059e7e768cabc2bcb7b276327bd6/03.STL/02.STL原理/img/traits.png -------------------------------------------------------------------------------- /03.STL/02.STL原理/img/traits2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hujiese/cpp-study/c94ec4adf61a059e7e768cabc2bcb7b276327bd6/03.STL/02.STL原理/img/traits2.png -------------------------------------------------------------------------------- /03.STL/02.STL原理/img/traits3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hujiese/cpp-study/c94ec4adf61a059e7e768cabc2bcb7b276327bd6/03.STL/02.STL原理/img/traits3.png -------------------------------------------------------------------------------- /03.STL/02.STL原理/img/traits4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hujiese/cpp-study/c94ec4adf61a059e7e768cabc2bcb7b276327bd6/03.STL/02.STL原理/img/traits4.png -------------------------------------------------------------------------------- /03.STL/02.STL原理/img/traits5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hujiese/cpp-study/c94ec4adf61a059e7e768cabc2bcb7b276327bd6/03.STL/02.STL原理/img/traits5.png -------------------------------------------------------------------------------- /03.STL/02.STL原理/img/traits6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hujiese/cpp-study/c94ec4adf61a059e7e768cabc2bcb7b276327bd6/03.STL/02.STL原理/img/traits6.png -------------------------------------------------------------------------------- /03.STL/02.STL原理/img/unordered_multimap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hujiese/cpp-study/c94ec4adf61a059e7e768cabc2bcb7b276327bd6/03.STL/02.STL原理/img/unordered_multimap.png -------------------------------------------------------------------------------- /03.STL/02.STL原理/img/unordered_multiset.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hujiese/cpp-study/c94ec4adf61a059e7e768cabc2bcb7b276327bd6/03.STL/02.STL原理/img/unordered_multiset.png -------------------------------------------------------------------------------- /03.STL/02.STL原理/img/vector.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hujiese/cpp-study/c94ec4adf61a059e7e768cabc2bcb7b276327bd6/03.STL/02.STL原理/img/vector.png -------------------------------------------------------------------------------- /03.STL/02.STL原理/img/vector2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hujiese/cpp-study/c94ec4adf61a059e7e768cabc2bcb7b276327bd6/03.STL/02.STL原理/img/vector2.png -------------------------------------------------------------------------------- /03.STL/02.STL原理/img/vector3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hujiese/cpp-study/c94ec4adf61a059e7e768cabc2bcb7b276327bd6/03.STL/02.STL原理/img/vector3.png -------------------------------------------------------------------------------- /03.STL/02.STL原理/img/vector4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hujiese/cpp-study/c94ec4adf61a059e7e768cabc2bcb7b276327bd6/03.STL/02.STL原理/img/vector4.png -------------------------------------------------------------------------------- /03.STL/02.STL原理/img/vector5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hujiese/cpp-study/c94ec4adf61a059e7e768cabc2bcb7b276327bd6/03.STL/02.STL原理/img/vector5.png -------------------------------------------------------------------------------- /03.STL/02.STL原理/reference/stl.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hujiese/cpp-study/c94ec4adf61a059e7e768cabc2bcb7b276327bd6/03.STL/02.STL原理/reference/stl.pdf -------------------------------------------------------------------------------- /03.STL/02.STL原理/src/01.test_array.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hujiese/cpp-study/c94ec4adf61a059e7e768cabc2bcb7b276327bd6/03.STL/02.STL原理/src/01.test_array.cpp -------------------------------------------------------------------------------- /03.STL/02.STL原理/src/02.test_vector.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hujiese/cpp-study/c94ec4adf61a059e7e768cabc2bcb7b276327bd6/03.STL/02.STL原理/src/02.test_vector.cpp -------------------------------------------------------------------------------- /03.STL/02.STL原理/src/03.test_list.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hujiese/cpp-study/c94ec4adf61a059e7e768cabc2bcb7b276327bd6/03.STL/02.STL原理/src/03.test_list.cpp -------------------------------------------------------------------------------- /03.STL/02.STL原理/src/04.test_forward_list.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hujiese/cpp-study/c94ec4adf61a059e7e768cabc2bcb7b276327bd6/03.STL/02.STL原理/src/04.test_forward_list.cpp -------------------------------------------------------------------------------- /03.STL/02.STL原理/src/05.test_deque.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hujiese/cpp-study/c94ec4adf61a059e7e768cabc2bcb7b276327bd6/03.STL/02.STL原理/src/05.test_deque.cpp -------------------------------------------------------------------------------- /03.STL/02.STL原理/src/06.test_queue.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hujiese/cpp-study/c94ec4adf61a059e7e768cabc2bcb7b276327bd6/03.STL/02.STL原理/src/06.test_queue.cpp -------------------------------------------------------------------------------- /03.STL/02.STL原理/src/07.test_stack.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hujiese/cpp-study/c94ec4adf61a059e7e768cabc2bcb7b276327bd6/03.STL/02.STL原理/src/07.test_stack.cpp -------------------------------------------------------------------------------- /03.STL/02.STL原理/src/08.test_multiset.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hujiese/cpp-study/c94ec4adf61a059e7e768cabc2bcb7b276327bd6/03.STL/02.STL原理/src/08.test_multiset.cpp -------------------------------------------------------------------------------- /03.STL/02.STL原理/src/09.test_multimap.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hujiese/cpp-study/c94ec4adf61a059e7e768cabc2bcb7b276327bd6/03.STL/02.STL原理/src/09.test_multimap.cpp -------------------------------------------------------------------------------- /03.STL/02.STL原理/src/10.test_unordered_multiset.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hujiese/cpp-study/c94ec4adf61a059e7e768cabc2bcb7b276327bd6/03.STL/02.STL原理/src/10.test_unordered_multiset.cpp -------------------------------------------------------------------------------- /03.STL/02.STL原理/src/11.test_unordered_multimap.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hujiese/cpp-study/c94ec4adf61a059e7e768cabc2bcb7b276327bd6/03.STL/02.STL原理/src/11.test_unordered_multimap.cpp -------------------------------------------------------------------------------- /03.STL/02.STL原理/src/12.test_set.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hujiese/cpp-study/c94ec4adf61a059e7e768cabc2bcb7b276327bd6/03.STL/02.STL原理/src/12.test_set.cpp -------------------------------------------------------------------------------- /03.STL/02.STL原理/src/13.test_map.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hujiese/cpp-study/c94ec4adf61a059e7e768cabc2bcb7b276327bd6/03.STL/02.STL原理/src/13.test_map.cpp -------------------------------------------------------------------------------- /03.STL/02.STL原理/src/14.test_unordered_set.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hujiese/cpp-study/c94ec4adf61a059e7e768cabc2bcb7b276327bd6/03.STL/02.STL原理/src/14.test_unordered_set.cpp -------------------------------------------------------------------------------- /03.STL/02.STL原理/src/15.test_unordered_map.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hujiese/cpp-study/c94ec4adf61a059e7e768cabc2bcb7b276327bd6/03.STL/02.STL原理/src/15.test_unordered_map.cpp -------------------------------------------------------------------------------- /03.STL/02.STL原理/src/16.test_accumulate.cpp: -------------------------------------------------------------------------------- 1 | #define _CRT_SECURE_NO_WARNINGS 2 | #include // std::cout 3 | #include // std::minus 4 | #include // std::accumulate 5 | using namespace std; 6 | 7 | namespace jj34 8 | { 9 | int myfunc(int x, int y) { return x + 2 * y; } 10 | 11 | struct myclass { 12 | int operator()(int x, int y) { return x + 3 * y; } 13 | } myobj; 14 | 15 | void test_accumulate() 16 | { 17 | cout << "\ntest_accumulate().......... \n"; 18 | int init = 100; 19 | int nums[] = { 10, 20, 30 }; 20 | 21 | cout << "using default accumulate: "; 22 | cout << accumulate(nums, nums + 3, init); //160 23 | cout << '\n'; 24 | 25 | cout << "using functional's minus: "; 26 | cout << accumulate(nums, nums + 3, init, minus()); //40 27 | cout << '\n'; 28 | 29 | cout << "using custom function: "; 30 | cout << accumulate(nums, nums + 3, init, myfunc); //220 31 | cout << '\n'; 32 | 33 | cout << "using custom object: "; 34 | cout << accumulate(nums, nums + 3, init, myobj); //280 35 | cout << '\n'; 36 | } 37 | } 38 | 39 | int main(void) 40 | { 41 | jj34::test_accumulate(); 42 | return 0; 43 | } -------------------------------------------------------------------------------- /03.STL/02.STL原理/src/17.test_for_each.cpp: -------------------------------------------------------------------------------- 1 | #define _CRT_SECURE_NO_WARNINGS 2 | #include // std::cout 3 | #include // std::for_each 4 | #include // std::vector 5 | using namespace std; 6 | 7 | namespace jj35 8 | { 9 | void myfunc(int i) { 10 | cout << ' ' << i; 11 | } 12 | 13 | struct myclass { 14 | void operator() (int i) { cout << ' ' << i; } 15 | } myobj; 16 | 17 | void test_for_each() 18 | { 19 | cout << "\ntest_for_each().......... \n"; 20 | 21 | vector myvec; 22 | myvec.push_back(10); 23 | myvec.push_back(20); 24 | myvec.push_back(30); 25 | 26 | for_each(myvec.begin(), myvec.end(), myfunc); 27 | cout << endl; //output: 10 20 30 28 | 29 | for_each(myvec.begin(), myvec.end(), myobj); 30 | cout << endl; //output: 10 20 30 31 | 32 | //since C++11, range-based for- statement 33 | for (auto& elem : myvec) 34 | elem += 5; 35 | 36 | for (auto elem : myvec) 37 | cout << ' ' << elem; //output: 15 25 35 38 | } 39 | } 40 | 41 | int main(void) 42 | { 43 | jj35::test_for_each(); 44 | return 0; 45 | } -------------------------------------------------------------------------------- /03.STL/02.STL原理/src/18.test_sort.cpp: -------------------------------------------------------------------------------- 1 | #define _CRT_SECURE_NO_WARNINGS 2 | #include // std::cout 3 | #include // std::sort 4 | #include // std::vector 5 | #include 6 | using namespace std; 7 | 8 | namespace jj36 9 | { 10 | bool myfunc(int i, int j) { return (i myvec(myints, myints + 8); // 32 71 12 45 26 80 53 33 22 | 23 | // using default comparison (operator <): 24 | sort(myvec.begin(), myvec.begin() + 4); //(12 32 45 71)26 80 53 33 25 | 26 | // using function as comp 27 | sort(myvec.begin() + 4, myvec.end(), myfunc); // 12 32 45 71(26 33 53 80) 28 | 29 | // using object as comp 30 | sort(myvec.begin(), myvec.end(), myobj); //(12 26 32 33 45 53 71 80) 31 | 32 | // print out content: 33 | cout << "\nmyvec contains:"; 34 | for (auto elem : myvec) //C++11 range-based for statement 35 | cout << ' ' << elem; //output: 12 26 32 33 45 53 71 80 36 | 37 | // using reverse iterators and default comparison (operator <): 38 | sort(myvec.rbegin(), myvec.rend()); 39 | 40 | // print out content: 41 | cout << "\nmyvec contains:"; 42 | for (auto elem : myvec) //C++11 range-based for statement 43 | cout << ' ' << elem; //output: 80 71 53 45 33 32 26 12 44 | 45 | // using explicitly default comparison (operator <): 46 | sort(myvec.begin(), myvec.end(), less()); 47 | 48 | // print out content: 49 | cout << "\nmyvec contains:"; 50 | for (auto elem : myvec) //C++11 range-based for statement 51 | cout << ' ' << elem; //output: 12 26 32 33 45 53 71 80 52 | 53 | // using another comparision criteria (operator >): 54 | sort(myvec.begin(), myvec.end(), greater()); 55 | 56 | // print out content: 57 | cout << "\nmyvec contains:"; 58 | for (auto elem : myvec) //C++11 range-based for statement 59 | cout << ' ' << elem; //output: 80 71 53 45 33 32 26 12 60 | 61 | return true; 62 | } 63 | } 64 | 65 | int main(void) 66 | { 67 | jj36::test_sort(); 68 | return 0; 69 | } -------------------------------------------------------------------------------- /03.STL/02.STL原理/src/96.Traits_problem.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hujiese/cpp-study/c94ec4adf61a059e7e768cabc2bcb7b276327bd6/03.STL/02.STL原理/src/96.Traits_problem.cpp -------------------------------------------------------------------------------- /03.STL/02.STL原理/src/97.Traits_solve.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hujiese/cpp-study/c94ec4adf61a059e7e768cabc2bcb7b276327bd6/03.STL/02.STL原理/src/97.Traits_solve.cpp -------------------------------------------------------------------------------- /03.STL/02.STL原理/src/sample.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hujiese/cpp-study/c94ec4adf61a059e7e768cabc2bcb7b276327bd6/03.STL/02.STL原理/src/sample.cpp -------------------------------------------------------------------------------- /04.内存管理/内存管理.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hujiese/cpp-study/c94ec4adf61a059e7e768cabc2bcb7b276327bd6/04.内存管理/内存管理.pdf -------------------------------------------------------------------------------- /04.内存管理/内存管理第五讲.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hujiese/cpp-study/c94ec4adf61a059e7e768cabc2bcb7b276327bd6/04.内存管理/内存管理第五讲.pdf --------------------------------------------------------------------------------