# C++ 学习
**Repository Path**: elliot1995/CPP_learn
## Basic Information
- **Project Name**: C++ 学习
- **Description**: C++ 学习
- **Primary Language**: Unknown
- **License**: MIT
- **Default Branch**: master
- **Homepage**: None
- **GVP Project**: No
## Statistics
- **Stars**: 1
- **Forks**: 1
- **Created**: 2019-11-11
- **Last Updated**: 2025-12-19
## Categories & Tags
**Categories**: Uncategorized
**Tags**: None
## README
# CPP 学习笔记
> 可以直接下载pdf [CPP 学习笔记](CPP学习笔记.pdf)
- [0.1. 多线程](#01-多线程)
- [0.1.1. 文件操作已经学完,今天看下多线程](#011-文件操作已经学完今天看下多线程)
- [0.1.1.1. 知识点1](#0111-知识点1)
- [0.1.1.2. 代码1](#0112-代码1)
- [0.1.1.3. 知识点2](#0113-知识点2)
- [0.1.2. 知识点3](#012-知识点3)
- [0.1.2.1. 代码3](#0121-代码3)
- [0.2. STL](#02-stl)
- [0.2.1. STL 学习,没有带笔记本回来。。。我日 2019.11.11 23:21](#021-stl-学习没有带笔记本回来我日-20191111-2321)
- [0.2.1.1. STL的概念](#0211-stl的概念)
- [0.2.1.2. 代码](#0212-代码)
- [0.2.1.3. STL抽象的是什么](#0213-stl抽象的是什么)
- [0.2.2. 六大组件](#022-六大组件)
- [0.2.2.1. vector 动态数组 堆上](#0221-vector-动态数组-堆上)
- [0.2.2.2. tuple 可以存储不同的数据类型](#0222-tuple-可以存储不同的数据类型)
- [0.2.2.3. list 适合经常插入,经常删除的情况](#0223-list-适合经常插入经常删除的情况)
- [0.2.2.4. list 容器](#0224-list-容器)
- [0.2.2.5. set 容器 (红黑树容器)](#0225-set-容器-红黑树容器)
- [0.2.3. algorithm 算法](#023-algorithm-算法)
- [0.2.4. Iterator](#024-iterator)
- [0.2.4.1. 仿函数](#0241-仿函数)
- [0.2.5. wmv STL Bug 迭代器](#025-wmv-stl-bug-迭代器)
- [0.2.6. wmv 栈队列双端队列优先队列](#026-wmv-栈队列双端队列优先队列)
- [0.2.6.1. stack 关键字可以构建栈](#0261-stack-关键字可以构建栈)
- [0.2.6.2. queue 队列](#0262-queue--队列)
- [0.2.6.3. deque 双端队列](#0263-deque-双端队列)
- [0.2.6.4. priority_que 优先级队列 (不太理解)](#0264-priority_que-优先级队列-不太理解)
- [0.2.7. 红黑树容器](#027-红黑树容器)
- [0.2.7.1. set 是一个红黑树](#0271-set-是一个红黑树)
- [0.2.8. set map multi-map 红黑树](#028-set-map-multi-map-红黑树)
- [0.2.8.1. set的高级用法](#0281-set的高级用法)
- [0.2.8.2. multiset](#0282-multiset)
- [0.2.8.3. map 映射 multimap 多层映射 9.wmv 53:41](#0283-map--映射-multimap-多层映射-nbsp9wmv-5341)
- [0.2.8.4. pair 关键字 9.wmv 01:23:15](#0284-pair-关键字-nbsp9wmv-012315)
- [0.2.8.5. hash_set 和hash_map 9.wmv 01:33:10](#0285-hash_set-和hash_map-nbsp9wmv-013310)
- [0.2.8.6. equal_range()](#0286-equal_range)
- [0.2.9. string 本质是一个容器](#029-string-本质是一个容器)
- [0.2.9.0.1. 网上扒来的 string 介绍](#02901-网上扒来的-string-介绍)
- [0.2.10. GPU编程](#0210-gpu编程)
- [0.2.10.1. Lamda 表达式 C++ AMP 编程](#02101-lamda-表达式-c-amp-编程)
- [0.3. 设计模式](#03-设计模式)
- [0.3.1. 备忘录模式](#031-备忘录模式)
- [0.3.2. 策略模式](#032-策略模式)
- [0.3.3. 设计模式 抽象工厂模式](#033-设计模式-抽象工厂模式)
- [0.3.4. 简单工厂模式](#034-简单工厂模式)
- [0.3.5. 方法工厂模式](#035-方法工厂模式)
- [抽象工厂模式](#抽象工厂模式)
- [单例模式](#单例模式)
- [代理模式](#代理模式)
- [迭代器模式](#迭代器模式)
- [命令行模式](#命令行模式)
- [责任链模式:](#责任链模式)
- [数据结构与算法](#数据结构与算法)
- [总览](#总览)
- [概论](#概论)
- [算法的特性](#算法的特性)
- [算法的衡量标准](#算法的衡量标准)
- [Boost和算法](#boost和算法)
- [boost Array 第一只boost 程序](#boost-array-第一只boost-程序)
- [boost 库的学习 boost_array_bind_fun_ref](#boost-库的学习-boost_array_bind_fun_ref)
- [std 方式](#std-方式)
- [boost方式](#boost方式)
- [boost::function 库](#boostfunction-库)
- [boost::ref](#boostref)
- [RAII](#raii)
- [智能指针 smartpointers 库](#智能指针-smartpointers-库)
- [类的虚函数表](#类的虚函数表)
- [一个自己实现的Vector(只能处理基本类型数据)](#一个自己实现的vector只能处理基本类型数据)
- [红黑树](#红黑树)
- [Boost 学习笔记](#boost-学习笔记)
- [有用的](#有用的)
- [Smart Pointer](#smart-pointer)
- [智能指针 :shared_ptr weak_ptr scoped_ptr scoped_array intrusive_ptr,](#智能指针-shared_ptr-weak_ptr-scoped_ptr--scoped_array--intrusive_ptr)
- [Smart_ptr 库如何改进你的程序?](#smart_ptr-库如何改进你的程序)
- [有三种典型的情况适合使用智能指针:](#有三种典型的情况适合使用智能指针)
- [boost智能指针的优势](#boost智能指针的优势)
- [scoped_ptr](#scoped_ptr)
- [scoped_ptr 的用法](#scoped_ptr-的用法)
- [scoped_ptr 和 Pimpl 用法](#scoped_ptr-和-pimpl-用法)
- [scoped_ptr 与 const auto_ptr 的区别](#scoped_ptr-与-const-auto_ptr-的区别)
- [总结](#总结)
- [scoped_array](#scoped_array)
- [shared_ptr](#shared_ptr)
- [作用](#作用)
- [Shared_ptr 定义](#shared_ptr-定义)
- [Shared_ptr 内部构造](#shared_ptr-内部构造)
- [代码示例](#代码示例)
- [QT 学习](#qt-学习)
- [0.1.1. 坐标系统](#011-坐标系统)
- [0.1.2. layouts](#012-layouts)
- [0.1.3. 控件](#013-控件)
- [0.1.4. 消息基础](#014-消息基础)
- [0.1.5. QT 消息中级](#015-qt-消息中级)
- [0.1.5.1. eventFilter 截取消息](#0151-eventfilter-截取消息)
- [1.0.5.2. notify 通知消息](#1052-notify-通知消息)
- [1.0.5.3. postEvent 和 sendEvent](#1053-postevent-和-sendevent)
- [1.0.6. QPainter 和重写自定义控件](#106-qpainter-和重写自定义控件)
- [1.0.6.1. QPainter 的绘图效率(引用)](#1061-qpainter-的绘图效率引用)
- [1.0.6.2. QPainter 实现自己的控件](#1062-qpainter-实现自己的控件)
- [1.0.7. 信号和槽](#107-信号和槽)
- [1.0.7.1. 定义](#1071-定义)
- [1.0.7.2. 需要注意的事项](#1072-需要注意的事项)
- [1.0.7.3. 总结:](#1073-总结)
- [1.0.8. 高级Painter](#108-高级painter)
- [1.0.9. QDialog](#109-qdialog)
- [1.0.9.1. 代码展示](#1091-代码展示)
- [1.0.10. MainWindow](#1010-mainwindow)
- [1.0.11. QFile-QBuffer-QXXXXStream-Mapping](#1011-qfile-qbuffer-qxxxxstream-mapping)
- [1.0.11.1. QFile](#10111-qfile)
- [1.0.11.2. QBuffer //内存 文件](#10112-qbuffer-内存-文件)
- [1.0.11.3. QDataStream QTextStream](#10113-qdatastream-qtextstream)
- [1.0.12. Socket-TCP-UDP-BOARDCAST-MULI-CAST](#1012-socket-tcp-udp-boardcast-muli-cast)
- [1.0.13. 关于在new 生成控件的时候this 的解释 和 deleteLater](#1013-关于在new-生成控件的时候this-的解释-和-deletelater)
- [1.0.13.1. 关于在new 生成控件的时候this](#10131-关于在new-生成控件的时候this)
- [1.0.13.2. deleteLater](#10132-deletelater)
- [1.0.14. QT动态库](#1014-qt动态库)
- [1.0.15. QT静态库](#1015-qt静态库)
- [1.0.16. QT JSON](#1016-qt-json)
- [1.0.17. QT 加密](#1017-qt-加密)
- [1.0.18. QSQLDatabase 的使用](#1018-qsqldatabase-的使用)
- [1.0.18.1. 编译Mysql 驱动](#10181-编译mysql-驱动)
- [1.0.19. QSQLDatabase 的使用](#1019-qsqldatabase-的使用)
- [1.0.19.1. 原生执行SQL语句](#10191-原生执行sql语句)
- [1.0.19.2. QSQLModel 方式 执行](#10192-qsqlmodel-方式-执行)
- [1.0.19.3. QTableView 特别方便](#10193-qtableview-特别方便)
- [1.0.20. Qprocess 的使用](#1020-qprocess-的使用)
## 0.1. 多线程
### 0.1.1. 文件操作已经学完,今天看下多线程
>> 2019.11.11 15:06
#### 0.1.1.1. 知识点1
Linux 下编译 带<thread> 的CPP需要加上 -pthread 编译选项。例如:
```
g++ -std=c++11 -pthread a.cpp
```
QT Creator 编译带<thread>的CPP有BUG,暂时不知道怎么去除!
#### 0.1.1.2. 代码1
```#include
#include v
#include
using namespace std;
void run(char* p)
{
int i=0;
i=system(p);
}
int main()
{
char p[5][20]={
"ls",
"echo nihao",
"gnome-terminal",
"terminator",
"ps -aux"
};
while("nimei")
{
static int i(0);
if(i<5){
thread *pt=new thread(run,p[i]);
i+=1;
cout<<"I now is :\t"<
#### 0.1.1.3. 知识点2
关于thread类的内部成
| 关键字 | 详细解释 |
| ---------------------------- | ---------------------------------------------------- |
| id | Thread的id |
| native_handle_type | native_handle_type |
| operator= | Move massive Thread |
| get_id | get Thread ID |
| joinable | get if joinable |
| join | join thread |
| detach | detach thread |
| swap | swap thread |
| native_handle | get native handle |
| hardware_concurrency[static] | Detect hardware concurrency (public static function) |

线程 detach 脱离主线程的绑定,主线程挂了,子线程不报错,子线程执行完自动退出。
线程 detach以后,子线程会成为孤儿线程,线程之间将无法通信。
### 0.1.2. 知识点3
线程中变量的竞争控制是通过 mutex automic 来实现的
mutex : 互斥量。需要包含头文件 <mutex> 来使用 -->速度慢
atomic 原子变量。需要包含头文件<atomic>来实现 -->速度快,线程安全。
#### 0.1.2.1. 代码3
```
#include
#include
#include
#include
using namespace std;
int count(0);
void run()
{
for(int i(0);i<1000000;i++)
{
count++;
cout<<"\t"<detach();
}
cout<<"Finally count is \t"<运行结果不是1000000×2.
```#include
#include
#include
#include
using namespace std;
int count(0);
void run()
{
for(int i(0);i<1000000;i++)
{
count++;
cout<<"\t"<detach();
}
cout<<"Finally count is \t"<运行结果是1000000×2.正确
atomic 声明方式为 atomic<int> a(100); 等号初始化会报错
vim 按CTRL+S 后假死按 CTRL+q 退出
## 0.2. STL
### 0.2.1. STL 学习,没有带笔记本回来。。。我日 2019.11.11 23:21
#### 0.2.1.1. STL的概念
Iterator (迭代器)
Container (容器) array
Alogrithm (算法)
Adapters (配接器) 用来实现容器之间的转接
面向过程--》面向对象-》基于对象-》泛型
#### 0.2.1.2. 代码
```
#include
#include //容器
#include //算法
using namespace std;
//专么实现一个类模板,实现打印
//类模板实现了方法
template
class vector_s {
public:
void operator()(const T &t1) //重载了小括号 实现访问小括号就直接打印
{
cout << t1 << endl;
}
};
int main(void)
{
vector myv;
myv.push_back(13);
myv.push_back(23);
myv.push_back(33);
myv.push_back(113);
myv.push_back(1995);
myv.push_back(1996);
vector_s print; // 对打印实现实例化
//myv.begin(), myv.end() 是迭代器 本质是指针
// for_each 本质是一个算法
for_each(myv.begin(), myv.end(), print);
cin.get();
return 0;
}
```
注意:算法需要包含头文件 <algorithm>
这个遍历的函数为 for_each 不是foreach
算法可以适用于任何容器
#### 0.2.1.3. STL抽象的是什么
-有些算法并不依赖于数据结构的特定实现,而只依赖于该结构的几个基本语义属性
-STL 抽象出的这些基本属性(concept)成功的将算法和数据结构相分离,在没有效率损失的前提下,获得了极大的弹性!
### 0.2.2. 六大组件
-容器 (container)
-算法Algorithm
-迭代器 (iterator)
-仿函数 (Function Object)
-适配器 (Adaptor)
-空间制配器 (allocator)
获取远程代码修改后,想要push到远端与原来不同的新分支,可以使用下面的命令实现:
git push origin 本地分支:远端希望创建的分支
例如git下来的分支为master
```
git branch master
git push origin master:my_remote_new_branch
#远端即可创建新的分支my_remote_new_branch,提交本地修改
```
``` std::for_each(arr.begin(), arr.end(), func);```
比较有用的for_each 用法
```for (auto n:Original)```
C++ 11 新的for
#### typename
- 成员函数也可以是模板-
- typename 作为类型前的标识符号-
```template
class MyClass
typename T::SubType * ptr; //typename 直接指示 T::SubType * 为一个类型 没有typename 会被解析为
// T域中的 SubType 静态成员 乘于(*) ptr.
...
};
```
-typename 的第二个作用:在模板声明中替换class -
```template class Myclass;```
#### static_cast 只有当类型转换有所定义,转换才会成功。(明确转换类型)
#### dynamic_cast 将多态类型向下转换\ 被转换的类必须有虚函数。否则失败
#### const_cast 用于转换为const 值
#### reinterpret_cast 多用于指针个的转换
#### C语言的小括号()可以替换除dymanic_cast 外的所有静态转换函数,无法明确显示使用他们的切确理由
### 容器的概念
-用于管理一组元素

#### 容器的分类
##### -序列式容器\(Sequence containers)
-每个元素都有固定位置--去结余插入时机和地点,和元素值无关
-vector list deque
##### 关联式容器 \(Associated containers)
-元素取决于特定的排序准则,和插入顺序无关
-set multiset map multimap

#### array
``` array ={1,2,3,4,5};```
-静态数组,栈上
#### 0.2.2.1. vector 动态数组 堆上
```vector mv;
mv.push_back()
```
-不需要变长,容量较小,array 需要变长,容量较大,用vector
#### 0.2.2.2. tuple 可以存储不同的数据类型
#### 0.2.2.3. list 适合经常插入,经常删除的情况
#### 0.2.2.4. list 容器
-list容器是无序容器
-list 容器只能通过迭代器访问。通过++ -- 遍历
-list容器可以使用remove()方法删除元素,
-可以同时正向和反向查找
-可以使用sort()函数排序
-可以使用merge 合并,但是合并之前必须排序
-可以使用unique()函数删除重复项,删除前必须排序。
--merge (使)合并,结合,并入;相融;融入;渐渐消失在某物中
#### 0.2.2.5. set 容器 (红黑树容器)
-set容器不能有重复项,重复的会被舍弃
-set容器会自动排序
-set 用insert插入元素
-set可以用find()函数查找位置
循环加栈
### 0.2.3. algorithm 算法
find()函数可以查找数组、容器中的元素。
for_each(); 遍历每一个元素。
multiset和set差不多,但是允许重复元素。
迭代器本质是智能指针。
### 0.2.4. Iterator

#### 0.2.4.1. 仿函数
```auto ifind=find_if(mylist.bengin(),mylisy.end(),bindlst(greater(),3));```
bindlst 需要头文件 funtional ```#include ```
```bindlst(greater(),3);``` 绑定一个函数。 ```greater() ``` 是一个仿函数(functional) 是一个重载了()的类/结构 体 ,可以用来实现一定的算法策略。
仿函数例子:
``` #include
#include
#include
#include
#include
using namespace std;
class shuchu {
public:
void operator()(int x)
{
std::cout<array1({1,2,3,4,5});
list ls1;
ls1.push_back(1);
ls1.push_back(3);
ls1.push_back(5);
ls1.push_back(7);
ls1.push_back(9);
auto ib=ls1.begin();
auto ie=ls1.end();
for_each(ib,ie,shuchu());
cin.get();
return 0;
}
```
### 0.2.5. wmv STL Bug 迭代器
>>2019.11.15
-智能指针有一个_Ptr属性,可以打印里面的指针。
-STL 有bug 先访问迭代器的_Ptr属性,再访问迭代器指针正常,但是反过来会出错。
-分行打印就没有问题。
### 0.2.6. wmv 栈队列双端队列优先队列
>> 2019.11.15
#### 0.2.6.1. stack 关键字可以构建栈
-用法
```stack ; //声明一个栈```
```mystack.push(num); //压栈```
```mystack.pop(); //出栈```
```mystack.top(); //获取第一个元素```
stack成员函数示例
-size( ) :返回栈中元素个数
-top( ) :返回栈顶的元素
-pop( ) :从栈中取出并删除元素
-push(e) :向栈中添加元素e
-empty( ) :栈为空时返回true
#### 0.2.6.2. queue 队列
-queue 英 [kjuː] 美 [kjuː]
n.(人、汽车等的)队,行列;(储存的数据)队列
v.(人、车等)排队等候;(使)排队;列队等待
-queue 需要头文件 \
-从网上拔来的Queue
[queue详解](queue.md)
queue 操作
queue 和 stack 有一些成员函数相似,但在一些情况下,工作方式有些不同:
-
front():返回 queue 中第一个元素的引用。如果 queue 是常量,就返回一个常引用;如果 queue 为空,返回值是未定义的。
-
back():返回 queue 中最后一个元素的引用。如果 queue 是常量,就返回一个常引用;如果 queue 为空,返回值是未定义的。
-
push(const T& obj):在 queue 的尾部添加一个元素的副本。这是通过调用底层容器的成员函数 push_back() 来完成的。
-
push(T&& obj):以移动的方式在 queue 的尾部添加元素。这是通过调用底层容器的具有右值引用参数的成员函数 push_back() 来完成的。
-
pop():删除 queue 中的第一个元素。
-
size():返回 queue 中元素的个数。
-
empty():如果 queue 中没有元素的话,返回 true。
-
emplace():用传给 emplace() 的参数调用 T 的构造函数,在 queue 的尾部生成对象。
-
swap(queue<T> &other_q):将当前 queue 中的元素和参数 queue 中的元素交换。它们需要包含相同类型的元素。也可以调用全局函数模板 swap() 来完成同样的操作。
queue<T> 模板定义了拷贝和移动版的 operator=(),对于所保存元素类型相同的 queue 对象,它们有一整套的比较运算符,这些运算符的工作方式和 stack 容器相同。
#### 0.2.6.3. deque 双端队列
- deque 可以从头部push_front()和尾部push_back()插入
- deque 可以使用迭代器 可以使用 迭代器+n 访问删除
- deque 可以pop_front() pop_back() 从头部和尾部 删除元素。
(1) 构造函数
deque():创建一个空deque
deque(int nSize):创建一个deque,元素个数为nSize
deque(int nSize,const T& t):创建一个deque,元素个数为nSize,且值均为t
deque(const deque &):复制构造函数
(2) 增加函数
void push_front(const T& x):双端队列头部增加一个元素X
void push_back(const T& x):双端队列尾部增加一个元素x
iterator insert(iterator it,const T& x):双端队列中某一元素前增加一个元素x
void insert(iterator it,int n,const T& x):双端队列中某一元素前增加n个相同的元素x
void insert(iterator it,const_iterator first,const_iteratorlast):双端队列中某一元素前插入另一个相同类型向量的[forst,last)间的数据
(3) 删除函数
Iterator erase(iterator it):删除双端队列中的某一个元素
Iterator erase(iterator first,iterator last):删除双端队列中[first,last)中的元素
void pop_front():删除双端队列中最前一个元素
void pop_back():删除双端队列中最后一个元素
void clear():清空双端队列中最后一个元素
(4) 遍历函数
reference at(int pos):返回pos位置元素的引用
reference front():返回手元素的引用
reference back():返回尾元素的引用
iterator begin():返回向量头指针,指向第一个元素
iterator end():返回指向向量中最后一个元素下一个元素的指针(不包含在向量中)
reverse_iterator rbegin():反向迭代器,指向最后一个元素
reverse_iterator rend():反向迭代器,指向第一个元素的前一个元素
(5) 判断函数
bool empty() const:向量是否为空,若true,则向量中无元素
(6) 大小函数
Int size() const:返回向量中元素的个数
int max_size() const:返回最大可允许的双端对了元素数量值
(7) 其他函数
void swap(deque&):交换两个同类型向量的数据
void assign(int n,const T& x):向量中第n个元素的值设置为x
[deque网上扒来的](deque.md)
#### 0.2.6.4. priority_que 优先级队列 (不太理解)
- 优先队列是按照堆来实现的
### 0.2.7. 红黑树容器
#### 0.2.7.1. set 是一个红黑树
### 0.2.8. set map multi-map 红黑树
#### 0.2.8.1. set的高级用法
- 红黑树,处理纯字符串比较少,处理字符串及对象比较多。
- pair 复合集合
- 二叉树查找依赖于有序。 字符串可以实现有序。
- pair 也是个类模板!起到获取插入返回值(boolean)的作用。两个参数,第一个类型,第二个是比大小的方法
- set的每一个节点就是一个节点
- 二叉树的实现语法一直在在在变 。VS2013 能过的 VS2017 就不能过了!~!!mingw 32又能过,代码如下:
- set 不能包含同样的值
- 0-35:40
```#include
#include
#include
#include
#include
using namespace std;
class strless
{
public:
bool operator () (const char* p,const char* p1)
{
return strcmp(p, p1) < 0;
}
private:
};
int main(void)
{
const char* cmd[] = { "nihao","spectrc","calc","good" };
setmyset(cmd,cmd+4,strless());
auto ib = myset.begin();
auto ie = myset.end();
for (auto i : myset)
{
cout << i << endl;
}
return 0;
}
```
#### 0.2.8.2. multiset
- 可以插入相同的值
- multiset 的每一个节点是一个链表
- 练习代码如下(mingw 32编译):
```#include
#include
#include
using namespace std;
class stu{
public:
int id;
char p[100];
};
class stuless
{
public:
bool operator ()(const stu &st1,const stu &st2)
{
return st1.id stu1 (student,student+3,stuless());
stu1.insert(newstu);
strcpy(newstu.p,"SBSBSBSB");
stu1.insert(newstu);
strcpy(newstu.p,"luo liuo");
stu1.insert(newstu);
for(auto i:stu1)
{
cout<< "\t"<
#### 0.2.8.3. map 映射 multimap 多层映射 9.wmv 53:41
- map 也是 红黑树,但是能同时映射多个数据
- map 需要头文件 \