C++笔记(《C++新经典》)
C++新经典
- 第1章 C/C++
- 1.1 C和C++语言的起源、特点、关系与讲解范畴
- 1.2 C/C++语言市场需求与就业需求分析
- 1.3 再谈C/C++就业
- 1.4 搭建开发语言环境
- 第2章 数据类型、运算符与表达式
- 2.1 常量、变量、整形、实型和字符型
- 2.1.1 创建最基本的C程序
- 2.1.2 C语言的数据类型
- 2.1.3常量和变量
- 2.1.4 整型数据
- 2.1.5 实型数据
- 2.1.6 字符型数据
- 2.1.7 字符串常量
- 2.1.8 变量赋初值
- 2.1.9 数值型数据之间的混合运算
- 2.2 算数运算符和表达式
- 2.2.1 C语言的运算符
- 2.2.2 算术运算符和算数表达式
- 2.2.3 运算符优先级问题
- 2.2.4 强制类型转换运算符
- 2.25 自增和自减运算符
- 2.3 复制运算符和逗号运算符
- 2.3.1 赋值运算符和赋值表达式
- 第3章 程序的基本结构和语句
- 第4章 程序的基本结构和语句
- 第5章 循环控制
- 第6章 数组
- 第7章 函数
- 第8章 编译预处理
- 第9章 指针
- 第10章 结构体与公用体
- 第11章 位运算
- 第12章 文件
- 第13章 C++基本语言
- 13.6函数新特性、inline内联函数与const详解
- 13.6.1 函数回顾与后置返回类型
- 13.6.2 inline内联函数
- 13.6.3 函数特殊写法总结
- 13.6.4 关于const char * 、char const *、char * const
- 13.6.5 函数形参中带const和&
- 13.7 string 类型
- 13.8 vector类型
- 13.9 迭代器精彩演绎、失效分析及弥补、实战
- 13.10 类型转换:static_cast 、reinterpret_cast
- 13.10.1 隐式类型转换
- 13.10.2 显式类型转换(强制类型转换)
- 第14章 类
- 第15章 模板与泛型
- 第16章 智能指针
- 第17章 并发与多线程
- 17.1 基本概念和实现
- 17.1.1 并发、进程、线程的基本概念
- 17.1.2 并发的实现方法
- 17.1.3 C++11新标准线程库
- 17.2 线程启动、结束与创建线程的方法
- 17.2.1 范例演示线程运行的开始和结束
- 17.2.2 其他创建线程的写法
- 17.3 线程传参详解、detach坑与成员函数作为线程函数
- 17.3.1 传递临时参数对象作为参数
- 17.3.2 临时对象作为线程参数继续讲
- 第18章 内存高级话题
- 第19章 STL标准模板库大局观
- 第20章 高级话题与新标准
- 后记 IT职业发展的未来之路
第1章 C/C++
1.1 C和C++语言的起源、特点、关系与讲解范畴
1.2 C/C++语言市场需求与就业需求分析
1.3 再谈C/C++就业
1.4 搭建开发语言环境
第2章 数据类型、运算符与表达式
2.1 常量、变量、整形、实型和字符型
2.1.1 创建最基本的C程序
2.1.2 C语言的数据类型
1.每种数据类型所占内存大小
2.每种数据的取值范围
2.1.3常量和变量
常量:字面值。
变量:值可以改变的量。
变量定义:类型名 变量名 [ = 变量初始值 ];
标识符:变量等等的取名。
保留字:系统保留的特殊用途的字。
2.1.4 整型数据
整数,包含所有进制。
2.1.5 实型数据
小数。
2.1.6 字符型数据
1.字符常量
‘a’ , ‘b’ ,‘1’
2.转义字符
‘\n’ ‘\’ ‘’’ …
3.字符变量
char c = ‘a’ ;
printf("c1=%c, c2=%c\n",c1,c2);
printf("c1=%d, c2=%d\n",c1,c2);printf("%f",num);
知识点: ASCII
2.1.7 字符串常量
printf("hello world!");/*
* 区分'a' "a"
* 字符串结尾多出来一个转义字符'\0',作为结束符
*
*/
注:Ctrl+F5 调试
Ctrl+F9 断点
Ctrl+F10下一断点
Shift +F9 添加监视
Ctrl Alt M +1 调用内存1(调试-窗口-内存-内存1)
2.1.8 变量赋初值
定义变量之后才能使用,一般是要赋初值的,否则会出错。
2.1.9 数值型数据之间的混合运算
不同数值类型的数据一起运算的的时候,系统尝试将变量类型统一。
类型转换从:
char , short ---->int ----> unsigned ----> long ----> double <-----double <----float
范围:由小变大。(隐式转换)
2.2 算数运算符和表达式
2.2.1 C语言的运算符
算数运算符 + - * 、 %(取余)
关系运算 <, <=, ==,>, >=,!=
逻辑运算符 !, &&, ||
位运算符 <<, >>, ~, |, ^, &
赋值运算符 =
条件运算符 ? :
逗号运算符 ,
指针运算符 * , &
求占字节运算符 sizeof()
强制类型转换符 (类型名)
成员变量运算符 . , ->
下标运算符 []
其他 …
2.2.2 算术运算符和算数表达式
2.2.3 运算符优先级问题
2.2.4 强制类型转换运算符
一般形式: (类型名)(表达式)
int a=1;
double b=(int) a;
总结:两种数据类型转换
- 自动类型转换,类型范围由小到大。
- 强制类型转换
都有精度损失或者溢出的风险。
2.25 自增和自减运算符
前++
后++
只适用于整型变量。
2.3 复制运算符和逗号运算符
2.3.1 赋值运算符和赋值表达式
第3章 程序的基本结构和语句
第4章 程序的基本结构和语句
第5章 循环控制
第6章 数组
第7章 函数
第8章 编译预处理
第9章 指针
第10章 结构体与公用体
第11章 位运算
第12章 文件
第13章 C++基本语言
13.6函数新特性、inline内联函数与const详解
13.6.1 函数回顾与后置返回类型
前置返回类型
int func( int a , int b);
int func( int a , int b)
{return a+b;
}
后置返回类型
auto func( int a, int b)->int ;
auto func( int a, int b)->int
{return a+b;
}
提示:一般一个函数写个几十到几百行就行,别太多,难以阅读。
13.6.2 inline内联函数
将简短且常用的函数定义为内联函数,代码在编译时被编译器会自动替换函数为函数体。
- 循环、分支、递归调用就不要使用内联修饰符。
- 内联函数类似 宏展开 #define 和 constexpr
inline int myfunc()
{return 1;
}
13.6.3 函数特殊写法总结
- 返回空
void func(int a, int b){a+b;
}
- 返回 值
int func(int a, int b){return a+b;
-返回指针
int * func(int b)
{int a=b;return &a;//函数一结束a就被释放,巨大隐患。
}
- 返回引用
int & func()
{int a=0;return a;//函数一结束a就被释放,巨大隐患。
}
- 采用形参返回
void func(int &a ,int &b)
{int temp=a;a=b;b=temp;
}
13.6.4 关于const char * 、char const *、char * const
关于修饰符:修饰符是从变量的旁边从右向左阅读
因此:
- const char * p ,* 先声明 p是指针,char 声明 指针指向的数据类型, const声明 不能通过指针p去修改p指的内容。
- char const * p,* 先声明 p是指针,const 声明不能通过指针p修改p指向的内容,声明 指针指向的数据类型。
- char * const p,const p p是一个常量, *声明这个常量是一个指向常量的指针,char常量指针指向的数据类型。
太难解释了,总之就是
- 指针常量,不能用指针求修改,指向的可以是常量,也可以是变量。(1,2)
-常量指针, 指针指向的是一个常量,不能指向非常量。(3)
13.6.5 函数形参中带const和&
先导:
形参的三种传值方式:
- 值传递
int add(int a, int b)
{cout<<"a的地址:"<<&a<<std::endl;cout<<"b的地址:"<<&b<<std::endl;}
int main()
{int c=1,d=2;cout<<"c的地址:"<<&c<<std::endl;cout<<"d的地址:"<<&d<<std::endl;add(c,d);
}
- 指针传递
int add(int *a, int *b)
{cout<<"a指向的地址:"<<a<<std::endl;cout<<"a的地址:"<<&a<<std::endl;cout<<"b指向的地址:"<<b<<std::endl;cout<<"b的地址:"<<&b<<std::endl;}
int main()
{int e=1,f=2;int *c=&e,*d=&f;cout<<"c的地址:"<<&c<<std::endl;cout<<"d的地址:"<<&d<<std::endl;add(c,d);
}
- 引用传递
int add(int &a, int &b)
{cout<<"a的地址:"<<&a<<std::endl;cout<<"b的地址:"<<&b<<std::endl;}
int main()
{int c=1,d=2;cout<<"c的地址:"<<&c<<std::endl;cout<<"d的地址:"<<&d<<std::endl;add(c,d);
}
综上,值传递需要消耗时间去复制实参到形参。
指针传递和引用传递是直接调用实参,效率更高。
函数参数带const
- 防止无意中修改形参值导致实参被修改
- 实参类型可以更加灵活
void func(const int & a)
{a=1;//不能通过a修改实参的值,报错。//引用传递,速度更快。
}
13.7 string 类型
13.8 vector类型
13.9 迭代器精彩演绎、失效分析及弥补、实战
迭代器仅仅是用来遍历容器的,若在遍历容器时,对容器进行修改,例如删除、添加的操作,会导致迭代器失效。
禁止迭代器使用时修改容器容量!
13.10 类型转换:static_cast 、reinterpret_cast
13.10.1 隐式类型转换
13.10.2 显式类型转换(强制类型转换)
C语言风格:
double b=10.1;
int a =(int) b;
C++四种强制类型转换
通用形式:
//强制类型转换名<type> (express);
- static_cast :静态转换,即编译时检查。
- 相关类型转换,如整型和浮点型之间的转换。
double f=10.2;
int a= static_cast<int> (f);
//类似
int b=(int ) f;
- 子类到父类的转换
class A{};
class B :public A{};
B b;
A a= static_cast<A> (b);
- void * 与其他类型指针之间的转换
void * 的指针可以指向任何指针类型。我感觉这个功能很鸡肋,懒得记载了。
不过,指针类型不可以进行强制类型转换,否则会出错。
dynamic_cast :运行时类型识别和检查
const_cast :用于去除指针或者引用的const属性,编译时检查。
在这里插入代码片
- reinterpret_cast
第14章 类
第15章 模板与泛型
第16章 智能指针
第17章 并发与多线程
17.1 基本概念和实现
17.1.1 并发、进程、线程的基本概念
1.并发
多个任务同时进行。(边听音乐边写作业,听音乐和写作是两不同的活动,但是同事进行。)
早期计算机只有一个CPU,为了同时间执行多个任务,我们规定在一定的时间间隔内执行程序,这样就可以在宏观上达到并行执行程序,但实际微观上是隔很短的时间不停的切换执行程序,这样看起来就像很多程序同时执行一样。
2.可执行程序
盘上的一个文件,window上是 .exe 结尾的文佳 ,Linux上面是 文件权限为 -rwxrw-r–的文件。
3.进程
可执行程序运行起来就是一个进程,总之就是一个运行的程序的过程就是进程。
4.线程
请先记住两件事:
- 每个进程都有一个主线程,这个主线程是唯一的。
- 当运行一个可执行程序,产生一个进程后,这个主线程也随之默默启动起来了。
总结:
- 线程是用来执行代码的
- 把线程理解成一条代码执行的通路,一个新的线程就代表一条新的道路。
- 一个进程自动办好了一个主线程,主线程随着进程的默默启动并运行,并可以包括多个其他线程(非主线程,是需要用代码来创建其他线程),但创建线程的数量最大一般不建议超过200~300个,具体还要针对实际程序。
- 因为主线程是自动启动的,所以一个进程中最少也是有一个线程的。
- 多线程可以同时做多件事情,所以运行效率更高,但是并不容易评估和量化,仍旧需要在实际编程和实际项目中体会和调整。
5.学习心得
戒骄戒躁,慢慢来。
17.1.2 并发的实现方法
1.多进程并发
多个程序同时运行。进程通讯三种方式:管道通讯、消息通讯和共享内存。
2.多线程并发
单个进程创建多个线程。线程通信代价更小,同一个进程的线程是共享地址空间,因此多线程并发开销更小。但是由于共享地址空间,数据一致性问题凸显。
3.总结
多线程并发的优缺点:
优点:线程启动速度更快,更轻量级,系统资源开销更少,执行速度更快。
缺点:使用起来有难度,要小心处理数据一致性问题。
17.1.3 C++11新标准线程库
C++11的线程库可以跨平台,使用起来更加方便。
17.2 线程启动、结束与创建线程的方法
17.2.1 范例演示线程运行的开始和结束
#include <iostream>
#include <thread>
using std::cout;
using std::endl;
void myprint()
{cout << "我的线程开始执行了!" << endl;//.......cout << "我的线程执行结束了。" << endl;return;}
int main()
{std::thread mytobj(myprint);//myprint作为构造函数参数mytobj.join();//main主线程等待子线执行//mytobj.detach();//主线程不会等待子线程cout << "main主函数执行结束了!" << endl;return 1;
}
(1)thread
一个类。构造函数的参数是一个可调用对象(此处可调用对象就是函数myprint)作为thread构造函数的实参来构造这个thread对象。
(2)join
阻塞函数,让main主线程等待子线程执行。(主线程结束,子线程会被强制结束)
(3)detach
分离函数,让main主线程不等待子线程执行。
(4)joinable
bool res=mytobj.joinable();//true为调用过。
判断某个线程是否调用过join或者detach函数。
17.2.2 其他创建线程的写法
1.用类来创建线程
#include <iostream>
#include <thread>
using std::cout;
using std::endl;class TA {public://重载“()”运算符void operator ()() {cout << "TA::operator()开始执行了" << endl;//...cout << "TA::operator()执行结束了" << endl;}
};int main()
{TA ta;std::thread myTObj(ta);myTObj.join();cout << "main主函数执行结束了!" << endl;return 1;
}
一些危险的操作:
/*
*使用detach后,当main函数执行结束后,
*很可能子线程还在访问主线程里面的*my_i,
*这个时候my_i早已被释放,子线程仍
*旧使用被销毁的ny_i,产生不可预料的
*后果。
*/
#include <iostream>
#include <thread>
using std::cout;
using std::endl;class TA {public:int& m_i;TA(int& i):m_i(i){}void operator ()() {cout << "mi1的值为:" << m_i << endl;cout << "mi2的值为:" << m_i << endl;cout << "mi3的值为:" << m_i << endl;cout << "mi4的值为:" << m_i << endl;cout << "mi5的值为:" << m_i << endl;cout << "mi6的值为:" << m_i << endl;cout << "mi7的值为:" << m_i << endl;cout << "mi8的值为:" << m_i << endl;cout << "mi9的值为:" << m_i << endl;}
};int main()
{int my_i = 6;TA ta(my_i);std::thread myTObj(ta);myTObj.detach();//main函数执行太快,延缓main,让线程函数执行for (int i = 0; i < 1000000; ++i) {int q;q = 1;}cout << "main主函数执行结束了!" << endl;return 1;
}
2.用lambda表达式来创建线程
#include <iostream>
#include <thread>
using std::cout;
using std::endl;auto myLamThread = [] {cout << "我的线程开始执行了" << endl;//...cout << "我的线程执行结束了" << endl;
};int main()
{std::thread myTObj(myLamThread);myTObj.join();cout << "main主函数执行结束了!" << endl;return 1;
}
17.3 线程传参详解、detach坑与成员函数作为线程函数
17.3.1 传递临时参数对象作为参数
1.要避免的陷阱1
主线程已经运行结束,资源已经释放,但是子线程仍然在调用主线程资源。
#include <iostream>
#include <thread>
using std::cout;
using std::endl;
using std::thread;
void myPrint(const int& i, char* pmyBuf)
{cout << i << endl;cout << pmyBuf << endl;return;
}int main()
{cout << "main主线程开始执行" << endl;int mvar = 1;int& mvary = mvar;char myBuf[] = "this is a test!";thread myTObj(myPrint, mvar,myBuf);myTObj.detach();cout << "main主函数执行结束了!" << endl;return 1;
}
2.要避免的陷阱2
传递的参数隐式转换时,还未来的及转换转换,资源就被释放。
#include <iostream>
#include <thread>
#include <string>
using std::cout;
using std::endl;
using std::thread;
using std::string;
void myPrint(const int& i, const &string pmyBuf)
{cout << i << endl;cout << pmyBuf << endl;return;
}int main()
{cout << "main主线程开始执行" << endl;int mvar = 1;int& mvary = mvar;char myBuf[] = "this is a test!";thread myTObj(myPrint, mvar,myBuf);myTObj.detach();cout << "main主函数执行结束了!" << endl;return 1;
}
总结:
- 若传递int这种简单类型参数,建议都使用值传递,不用用引用类型,避免节外生枝。
- 若传递类对象作为参数,则避免隐式转换(例如把一个char * 转换成string,一个int转成类A对象),全部都在创建线程这一行就构造出临时对象来,然后仙城入口函数的形参位置使用引用来作为形参(如果不使用引用可能在某种情况下导致多构造一次临时对象,不单浪费,且会造成新的潜在问题)。
- 总计结论:使用join就没有这个问题了。
17.3.2 临时对象作为线程参数继续讲
1.线程id概念
每个线程对应这不同的id。
使用:std::this _thread::get_id()、
2.临时对象构造时机抓捕
第18章 内存高级话题
第19章 STL标准模板库大局观
第20章 高级话题与新标准
后记 IT职业发展的未来之路
C++笔记(《C++新经典》)相关推荐
- C++新经典——C++从入门到精通
目录 专栏目的 章节目录: 开发环境: 专栏目的 博主开这一个专栏博客的目的是复习巩固博主之前学的C++知识点, 也就是 王健伟老师的C++书籍 <C++新经典>读书笔记 后续会将所有的部 ...
- 本站视频相关的C++新经典系列书籍出版
C++新经典系列书籍出版 各位学友,<C++新经典>.<C++新经典:对象模型>两本书已经出版! 其中<C++新经典>书中的内容包含了老师在本站所发布的视频教程& ...
- 本站视频相关C++新经典系列书籍再出一本
各位学友,<C++新经典:Linux通信架构实战>书籍已经出版! 这本书的内容包含了老师在本站所发布的视频教程<Linux C++网络编程>,建议大家在本站购买视频学习时也顺便 ...
- 《C++新经典》第1章 C/C++语言
<C++新经典>第1章 C/C++语言 C语言最突出特点: 效率高. 灵活性.可以直接访问物理地址(操作硬件),进行位运算. C++语言特性:封装性.继承性.多态性. Visual Stu ...
- 《C++新经典Linux C++通信架构实战》第2章 进入Nginx之门
<C++新经典Linux C++通信架构实战>第2章 进入Nginx之门 2.1 Nginx简介.选择理由.安装和使用 2.1.1 Nginx简介 2.1.2 为什么选择Nginx 2.1 ...
- 好教程推荐系列:《C++新经典》和《Visual C++ 2017从入门到精通》
C++新经典 C++新经典:Linux C++通信架构实战 C++新经典:对象模型 C++新经典:模板与泛型编程 C++新经典:设计模式 作者:王建伟,网名:KuangXiang c++11并发与多线 ...
- 《C++新经典Linux C++通信架构实战》第1章 课程介绍
<C++新经典Linux C++通信架构实战>第1章 课程介绍 1.1 本书内容详细介绍 1.1.1 内容总述 1.1.2 为什么选择Linux操作系统平台 1.1.3 讲解规划和学习建议 ...
- 咸鱼CAD笔记—2018切换经典模式
咸鱼CAD笔记-2018切换经典模式 1.打开CAD2018在界面右下角,点击辅助状态栏里倒三角,点击自定义. 2.打开自定义的界面,在折叠图标中打开"工作空间",选择" ...
- 《泰晤士报》百本新经典童书推荐-0-3岁宝宝阅读
<泰晤士报>近期推出的<百本新经典分级阅读童书推荐>选取了最近10年出版的100本最值得推荐的童书.该书单由牛津大学毕业的英国作家和童书评论家.多项童书大奖的评委妮可莱特.琼斯 ...
- iOS最新面试题4【经典】_技术成长笔记_新浪博客
游戏题: 1.项目介绍: 你所在的团队要开始一项为期4个月的iPhone游戏项目.在团队开始工作之前,游戏引擎要支持一些功能. 任务一: 添加触屏支持(创建一个iPhone应用程序,让玩家能用3根 ...
最新文章
- c++中的vector的常见使用
- Windows 下使用Git管理Github项目
- 查看mysql日志文件大小和数据库大小
- sqoop导入数据到hive中元数据问题
- NYOJ 597 完数?
- Vue+ElementUI: 手把手教你做一个audio组件
- stm32编程入门_电子设计与单片机编程书籍资料推荐
- python中continue只结束本次循环_循环(while,break,continue),转义字符
- IntelliJ IDEA导入Maven之后强制刷新项目解决无法识别为Maven项目的问题
- 把核心代码全开源,还能做出卡别人脖子的产品吗?
- 有关ACM学习的博客链接
- android图片拖动放大_Android拖放
- iOS cocoapods的使用规范说明及示例(.podspec配置文件)
- jquery遍历的radio的取值问题
- [工程经验] 电气与控制系统设计方案(框架)- 机器人
- java oracle数据备份_Java实现Oracle数据库备份
- ORA-12514 错误的处理
- 如何手动创建NVivo主题节点?
- 回溯法解决01背包-非递归算法-效率低
- SCP 从Linux下载文件到Windows本地
热门文章
- 使用Excel条件格式-重复值
- 秒变“女装大佬”!Snapchat推出性别转换滤镜,离线实时渲染(附测评)
- 【Hadoop的初级理解】
- 身份证真伪辨别python版
- win10html网页运行空白,win10系统Ie浏览器无法打开HTML格式的网页文件的处理秒方...
- 关于二重积分,三重积分的理解
- 计算机主机配置科普,电脑装机配置 篇八:电脑内存如何选购?内存科普--小白篇...
- ESP8266+1.3“ or 0.96“ OLED两个太空人动画(胖子和瘦子)
- 1.(python)阿拉伯数字转中文大写
- 北斗短报文的工作原理及作用