
C++ Primer plus笔记
C++ Primer plus 读书笔记
持续学习,不断沉淀
C++开发工程师
展开
-
C++类模板与函数模板介绍
类模板、类模板的全特化、类模板偏特化、成员函数模板、类模板的类型模板参数携带默认类型、类模板的非类型模板参数携带默认值、函数模板、函数模板全特化原创 2023-06-02 17:58:54 · 576 阅读 · 0 评论 -
C++文件读写类介绍
C++输入输出标准库拥有输入输出模板类及两个标准实例化集:一个是用于操作char类型元素的实例化集(即常用的cin,cout等),另一个用于操作wchar_t类型元素的实例化集。原创 2023-04-27 10:35:54 · 958 阅读 · 0 评论 -
C++程序异常退出问题总结
根据异常退出调用栈中的fault_address猜测异常原因:1、fault_address=0x0 空指针2、fault_address=较小的地址:野指针(空指针加偏移地址取数据)3、fault_address=较大的地址:野指针三个例子:1、A类对象A_C将其成员函数A_x注册给B类对象B_C,类对象B_C调用函数A_x导致异常退出原因: 类对象A_C析构后未解注册其成员函数A_x到类对象B_C,来将函数A_x指针置空。类对象B_C调用函数A_x时指针为野指针导致异常。经验:类对象析原创 2022-02-12 20:30:00 · 2538 阅读 · 0 评论 -
auto与decltype用法
1、auto类型推导auto varname = value;auto 根据=右边的初始值value推导出变量的类型2、decltype类型推导decltype(exp) varname = value;decltype根据exp表达式推导出变量的类型,跟=右边的value没有关系。3、auto与decltype结合类型推导auto此时不表示自动类型检测,作为返回值类型后置时的占位符,是表示后置返回值的语法的一部分。decltype声明返回值类型。例:template<class原创 2022-04-16 10:15:00 · 788 阅读 · 0 评论 -
博客转载:1.map和unordered_map对比; 2.struct的初始化和赋值
1、C++标准库中std::map和std::unordered_map对比及如何选择2、c++中结构体struct的初始化和赋值操作转载 2022-02-13 11:30:00 · 247 阅读 · 0 评论 -
static_cast<void>(0)与(void)0及在宏中的应用
1、static_cast<void>(0)和(void)0的意义:1.1:作用:C++中的的static_cast<void>(0)和C语言的(void)0作用一样,都表示将0强制转换为void类型,表示一个空语句。1.2:原理:任何表达式都可以显示地转换为void类型。而0事实上是一个表达式,所以(void)0的涵义就是将表达式0显示地转换为void类型。转换前后的区别在于:转换之前,表达式0的值为int类型0;而转换之后,表达式(void)0的值为void。2、宏中的原创 2022-02-12 13:00:00 · 1398 阅读 · 0 评论 -
NOLINT注释的意思
1、现象:int x = 100; // NOLINT2、解释:原文: What is //NOLINT?That’s a comment. In this case, it’s a comment designed to be read by a static analysis tool to tell it to shut up about this line.I’d guess that the tool being used complains about this line of co原创 2020-11-05 00:12:17 · 7968 阅读 · 2 评论 -
段错误学习记录
4、段错误:通常该错误是由于调用一个地址,而该地址为空(NULL)所造成的,例如链表中调用一个未分配地址的空链表单元的元素。数组访问越界也可能产生这个错误。参考网址:1、Linux环境下段错误的产生原因及调试方法小结2、百度百科-段错误3、维基百科-存储器区段错误...原创 2020-11-08 00:37:19 · 111 阅读 · 0 评论 -
uint8_t、uint16_t、uint32_t、DWORD都是什么类型?
1、*_t是什么意思:它是一个结构的标注,可以理解为type/typedef的缩写,表示它是通过typedef定义的。2、*_t与常用数据类型对应关系:uint8_t,uint16_t,uint32_t只是使用typedef给类型起的别名。为了用户的方便,C99标准的C语言硬件为我们定义了这些类型,按照posix标准,一般整形对应的*_t类型为:1字节uint8_ttypedef unsigned char uint8_t无符号8位数1字节int8_ttypedef转载 2020-07-19 22:29:06 · 7083 阅读 · 3 评论 -
memcpy与memcpy_s、memmove与memmove_s、sprintf与sprintf_s的区别
1、memcpy与memcpy_s:两函数原型:void* memcpy( void *restrict s1, const void *restrict s2, size_t n); errno_t memcpy_s( void *dest, // dest:目标的地址 size_t numberOfElements, // numberOfElements:目标的size const void *src, // src:源地址 size_t count); // count:要原创 2020-07-19 23:16:16 · 4242 阅读 · 0 评论 -
宏定义中的#,##,#@,\符号用法
1、字符串化操作符(#):给参数x加双引号作用: 将宏定义中传入的参数名转换成用一对双引号括起来的字符串。其只能用于有传入参数的宏定义中,且必须置于宏定义体中的参数名前。用法:#define ToString(x) #xchar* str = ToString(123132); // 就成了str="123132";2、连接操作符(##):作用: 将两个参数按字面值连接成一个参数用法:#define Conn(x,y) x##y int n = Conn(123,456); //转载 2021-05-23 21:13:54 · 5027 阅读 · 0 评论 -
C++头文件包含(2):cpp多次包含同一头文件,会有什么问题?头文件保护
1、目录结构:/base /main main.cpp CMakeLists.txt /test1 test.h 2、文件内容:2.1、不加头文件保护:多次包含重定义问题// main.cpp #include "test.h" #include "test.h" int main() { func(); return 0; } // CMakeLists.txt i原创 2021-04-21 21:32:54 · 2050 阅读 · 1 评论 -
C++头文件包含(1):cpp包含不同目录的同名头文件,实际使用哪个头文件?
1、目录结构:/base /main main.cpp CMakeLists.txt /test1 test.h /test2 test.h 2、文件内容:// main.cpp #include "test.h" int main() { func(); return 0; } // CMakeLists.txt include_directories(${CMAKE_SOU原创 2021-04-21 21:27:09 · 3278 阅读 · 0 评论 -
有符号/无符号整数相加溢出的判断方法
1、有符号数相加溢出判断:1、当两个有符号整数x,y同为正数,且x+y的结果为非正时,发生了正溢出:int x; int y; int s = x + y; if (x > 0 && y > 0 && s < 0) { cout << "发生了正溢出:符号位的1被覆盖为0" << endl; } 2、当两个有符号整数x,y同为负数,且x+y的结果为非负时,发生了负溢出:if (x < 0 &&a原创 2021-04-15 22:25:49 · 10322 阅读 · 0 评论 -
可变参数列表__VA_ARGS__介绍
一、概念介绍:1、...:表示可变参数列表。2、__VA_ARGS__:表示是一个可变参数的宏。3、args...:表示可变参数列表,表示后续的args可能会有多个。4、args:表示是一个可变参数的宏。二、基础应用:#define LOG1(...) func1(__VA_ARGS__) #define LOG2(args...) func1(args) __VA_ARGS__作用: 将左边宏中的’…'的内容原样抄到右边__VA_ARGS__所占用的位置。 以上两宏等价。#def原创 2021-04-09 22:12:34 · 4903 阅读 · 0 评论 -
const函数参数、成员函数限制
总结: const修饰的变量、函数,都不能修改其所在对象相关的内容,包括其成员变量中的内容。1、const函数参数:class Base { public: void test() { std::cout<< " test in base\n"; } }; void MyTest(const Base& b) { b.test(); // 这里编译报错,const对象调用非const成员函数。 } 原因: const对象,只能原创 2021-04-06 21:39:04 · 1091 阅读 · 0 评论 -
C语言内置宏:显示当前源文件名(__FILE__)、代码行号(__LINE__)、函数名(__FUNCTION__)
1、ANSI C标准中常用的预定义宏:DATE: 在源文件中插入当前的编译日期TIME:在源文件中插入当前编译时间;FILE:在源文件中插入当前源文件名;LINE:在源代码中插入当前源代码行号;FUNCTION:在源代码中插入当前所在函数名称;STDC:当要求程序严格遵循ANSI C标准时该标识被赋值为1;__cplusplus :当编写C++程序时该标识符被定义。2、使用展示:// test.cpp int main() { cout << "file转载 2021-04-06 21:31:12 · 2024 阅读 · 0 评论 -
auto推导规则
1、示例:int x = 0; auto *a = &x; //a->int*,auto被推导为int auto b = &x; //b->int*,auto被推导为int* auto &c = x; //c->int&,auto被推导为int const auto d = x; //d->const int,auto被推导为int auto e = c; //e->int,auto被推导为int,原创 2021-04-06 21:21:05 · 608 阅读 · 0 评论 -
类继承后,不同修饰符public、protected、private下成员属性访问变化
总结: 基类中成员变量想要在子类中访问,最好放在protected下 (private下子类访问不到,public下暴露太广) 。1、 private,public,protected的访问范围:private: 只能由该类中的函数、其友元函数访问,不能被任何其他访问,该类的对象也不能直接访问;protected: 可以被该类中的函数、子类的函数、以及其友元函数访问,但不能被该类的对象直接访问;public: 可以被该类中的函数、子类的函数、其友元函数访问,也可以由该类的对象访问注:友元函数包括转载 2021-03-31 21:17:16 · 1553 阅读 · 0 评论 -
正则表达式常用元字符注释及常用表达式
1、常用元字符注释:“.”: 匹配除"\n"之外的任何单个字符,若要匹配包括"\n"在内的任意字符,需使用诸如"[\s\S]"之类的模式;“^”:匹配输入字符串的开始位置,不匹配任何字符,要匹配”^”字符本身,需使用”\^”;“$”:匹配输入字符串结尾的位置,不匹配任何字符,要匹配”$”字符本身,需使用”\$”;“*”: 零次或多次匹配前面的字符或子表达式,”*”等效于”{0,}”,如”\^*b”可以匹配”b”、”^b”、”^^b”、…;“+”: 一次或多次匹配前面的字符或子表转载 2021-01-31 21:31:24 · 223 阅读 · 0 评论 -
-1的原码、反码、补码(0xff)
-1的表示1、0xff的无符号数为255,当作为有符号数显示则为-1。2、-1的原码表示为1001;除符号位取反得反码:1110;加1得补码:1111即0xff。3、负数在计算机中用补码表示。参考资料:c++ 2、机器数、真值、原码、补码、反码...原创 2021-01-24 21:39:47 · 15905 阅读 · 0 评论 -
构造函数初始化列表中变量的初始化顺序与变量的声明顺序关系
1、结论:构造函数初始化列表中对变量的初始化顺序与变量的声明顺序需要保持一致2、不一致导致的后果案例:输出为一个随机数和98,为什么呢?因为对于初始化列表而言,对成员变量的初始化,是严格按照声明次序,而不是在初始化列表中的顺序进行初始化,如果改为赋值初始化则不会出现这个问题,当然,为了使用初始化列表,还是严格注意声明顺序吧。3、打开编译选项让初始化顺序与声明顺序不一致时报错来减少编程错误。学习链接:构造函数初始化列表中对变量的初始化顺序与变量的声明顺序一致...转载 2020-12-20 16:13:04 · 1218 阅读 · 0 评论 -
C++中使用基类指针调用只存在派生类的方法
1、将基类指针转换为派生类指针,去调用。具体方法见:C++中使用基类指针调用派生类中定义的方法核心代码:A *p = new B;dynamic_cast<B*>(p)->func(); // cast A* to B*不转换找不到的原因:基类空间内不存在该函数,虚表内也不存在。只存在派生类的空间内。因此只能派生类指针调用。2、在基类中声明该函数,直接用基类指针调用。可以不用实现该方法,即(虚函数)。...原创 2020-11-14 17:58:21 · 2040 阅读 · 0 评论 -
cin.get()、cin.get(str, Size)与cin.getline(str,Size)的区别及其对空行的处理
1、cin.get(str, Size)读取Size个字符或直到遇到\n时止,并且将\n留在输入缓冲区中,其将被下一个读取输入的操作捕获。2、cin,get()cin.get( )的一个重载函数:使用不带任何参数的cin.get()可读取缓冲区的下一个字符(即使是换行付),因此可以用它来处理换行符,为读取下一行输入做好准备。3、cim.getline(str,Size)读取Size个字符或直到遇到\n时止,并且将\n直接从输入缓冲区中删除掉,不会影响下面的输入处理。当输入的字符数超出Size的大原创 2020-11-01 21:06:07 · 841 阅读 · 0 评论 -
C++中cout输出字符型指针地址值的方法:static_cast<void *>(char*)
1、字符串指针无法输出地址值的原因:由于C++标准库中I/O类对<<操作符重载,因此在遇到字符型指针时会将其当作字符串名来处理,输出指针所指的字符串。2、解决方法:既然这样,那么我们就别让它知道那是字符型指针,所以得用到强制类型转换,用static_cast来实现,把字符串指针转换成无类型指针,如下:int main(){ const char *pszStr = "this is a string"; // 输出字符串 cout << "字符串:"转载 2020-10-18 22:02:39 · 2139 阅读 · 1 评论 -
不同类型变量相加问题:unsigned int + int
1、案例现象:不同类型值相加结构与理想值不一致。int main(){ int i = -20; unsigned int j = 10; cout << i + j << endl; system("pause"); return 0;}输出结果:4 294 967 2862^32-10=4 294 967 296-10=4 294 967 2862、原因:两个兼容的不同类型的值相加,哪个数能表示更大的数(正数)就转为那个数转载 2020-09-13 21:57:57 · 3792 阅读 · 1 评论 -
大数求余:即答案对1e9+7(1000000007)取模原因、方法总结
1、大数求余原因:大数越界大数越界:随着n增大,f(n)会超过Int32甚至Int64的取值范围,导致最终的返回值错误。当一个问题只对答案的正确性有要求,而不在乎答案的数值,可能会需要将取值很大的数通过求余变小。2、求余运算规则:设正整数x,y,p,求余符号为⊙。对于加法运算:(x+y)⊙p = (x⊙p+y⊙p)⊙p对于乘法运算:(x*y)⊙p = [(x⊙p)*(y⊙p)]⊙p以防x,y本身就超出int32范围,可以创建一个long型变量tmp保存临时结果。例题:1、面试题14- II原创 2020-06-15 15:47:31 · 14359 阅读 · 0 评论 -
负数取绝对值时小心越界:如abs(-2147483648)、-(-2147483648)
有时解题中需要将变量n转为正数处理,而在变量n取值范围很大时,如32位有符号整数[−231, 231 − 1] ,需要注意转换时越界问题。int取值范围Value二进制[−231, 231 − 1]十进制[-2147483648, 2147483647]十六进制[0x80000000, 0x7fffffff]1、越界现象:以下函数,当传入参数n为-2147483648,转换为正数时会发生越界问题。void myFunc(double x, int n) {原创 2020-06-12 16:27:52 · 2923 阅读 · 0 评论 -
C++数组初始化方式:for循环或memset
1、默认初始化:int arr[26] = {1}; // 初始化为{1,0,0,。。。,0}注:初始化列表只初始化指出位置处的元素,其他位置默认初始化为0。参考资料: C/C++数组初始化2、for循环初始化:int arr[26] = {1}; for(int i = 0; i<26;i++){ // 全部初始化为-1 arr[i] = -1;} 3、memset初始化:int arr[26] = {-1}; memset(arr, -1, sizeof(arr))原创 2020-05-14 10:50:05 · 2037 阅读 · 0 评论 -
C++11使用using代替typedef定义类型别名:更直观
1、typedef定义类型别名:传统的定义类型别名的方法是使用关键字typedef:typedef long long LL;缺点:需要记住前后位置顺序,且不直观。2、使用#define来定义别名(使用预处理器,直接替换):#define LL long long缺点:为直接替换,存在#define的等等缺点,且需要记住前后位置顺序,不直观。3、 在C++11中使用关键字using来进行别名声明:using LL = long long;LL val = 1;参考资料:C++11原创 2020-05-13 12:32:06 · 2774 阅读 · 0 评论 -
C++中动态、静态二维数组指针做函数参数的用法
1、二维静态数组指针:int arr[3][2] = {{1,2},{3,4},{5,6}};调用函数定义方式:int func1( int (*arr)[2], int size ){ // size表示数组的大小,应是3 arr[1][1] = 5;...}或int sum( int arr[][2] , int size ){...} //2必须指定arr是一个数组名,该数组有3个元素,第一个元素本身又是一个数组,有2个int 值组成。因此,arr的类型是指向2个int组成的数组的原创 2020-05-11 09:26:25 · 3651 阅读 · 0 评论 -
非static成员函数可访问static态成员函数/成员;static成员函数不能访问非static成员函数/成员,只能访问static成员函数/变量
1、static成员函数不能访问非static成员函数/成员,只能static成员间相互访问://.hclass A{public: static func1() // 编译出错 { menber1 = 1; } static func3() { cout<<"abc"<<endl; } static func2()...原创 2020-04-01 16:40:39 · 6520 阅读 · 2 评论 -
函数指针变量声明与typedef函数指针类型声明
1、定义函数指针变量:char (*pFun)(int); //函数指针变量char glFun(int a){ return;} //函数pFun = glFun; //函数指针赋值(*pFun)(2); //函数调用其中pFUN是函数指针变量。2、定义函数指针类型:typedef char (*Typefunc)(int); //函数指针类型char glFun(int a)...原创 2020-03-31 18:24:39 · 418 阅读 · 0 评论 -
const对象只能调用const成员函数、不能调用非const成员函数;非const对象可以调用const成员函数
引发原因: 由调用成员函数时隐式传入的当前对象的this指针引起。1、 非const成员函数中的隐式参数:classA* this2、 const成员函数中的隐式参数:const classA* this根本原因:1、 const对象的指针为const classA* this,因此传入非const成员函数时编译器报错(类型不匹配,无法从const 指针转换为非const指针);但传入co...原创 2020-03-30 15:36:30 · 5488 阅读 · 4 评论 -
在派生类中使用using声明改变基类成员的可访问性
原文:通过在类的内部使用using声明语句 , 我们可以将该类的直接或间接基类中的任何可访问成员标记出来 (只限于非私有成员) 。using声明语句中名字的访问权限由该using声明语句之前的访问说明符来决定。例子://.hclass Base{public: int base_public = 1; void func1();protected: int base_prote...原创 2020-03-27 17:15:21 · 1863 阅读 · 0 评论 -
is-a与has-a区别:基类指针/引用不能指向protected与private的派生类对象
1、基类指针/引用不能指向protected与private的派生类对象:例子://.hclass A{ ...};class B: private A{ ...};//.cppvoid func1(const A& a){...}A a;B b;func1(a); // 成功,基类引用指向基类对象func1(b); // 编译失败,私有继承下,基类引用无法指...原创 2020-03-22 10:44:26 · 472 阅读 · 0 评论 -
变量函数链接性与名称空间
1、局部变量:无链接性2、函数外定义的变量:static变量:内部链接性const常量:内部链接性(相当于有了static属性)其他变量:外部链接性3、函数:外部链接性static函数:内部链接性名称空间1、名称空间可以使全局的,也可以位于另一个名称空间中,但不能位于代码块中。因此,在默认情况下,在名称空间中声明的名称的链接性为外部(除非引用了常量)2、未命名名称空间name...原创 2020-02-26 20:37:21 · 261 阅读 · 0 评论 -
个人学习笔记:inline函数与宏定义
C++中设计inline函数目的:用它***替代C中表达式形式的宏定义***:#define。内联函数作用:定义inline函数即推荐编译器将函数定义放在调用此内联函数位置,提高代码运行速度,但以运行内存为代价。宏定义:#define缺点1、仅是做预处理器符号表中的简单替换,无参数有效性检测,也就不能享受C++编译器严格类型检查的好处,另外它的返回值也不能被强制转换为可转换的合适的类型。...原创 2020-02-19 16:56:44 · 186 阅读 · 0 评论 -
斜线/、反斜线\、双斜线//、双反斜线\\——详解
读法:/ | \ 三个符号,中为正,左为斜线,右为反斜;八字,先撇为斜,后捺为反斜。用法介绍:1、//双斜线: 协议和主机名之间的分隔符,固定用法。例:https://www.baidu.com/超链接的url是以双斜杠“//”开头的,是依赖协议的URL表示形式,这种写法会判断当前的页面协议是http,https 或其他来决定请求 url 的协议。2、/单斜线: WEB上或者Unix内核的...原创 2020-01-13 17:54:17 · 22545 阅读 · 0 评论 -
explicit与隐式类型转换
1、普通类型通过隐式转换为类类型:类声明中只接受一个参数的构造函数可以进行隐式类型转换,例子:// .hClass Stone{private: double abc;public: Stone() {} Stone(double para1){abc = para1;} Stone_show(){cout<<abc;}};//.cppStone s1;s1...原创 2020-03-15 16:25:22 · 310 阅读 · 0 评论