C++ primer plus (第6版)里的技术点(1)
2015-01-16 21:48
162 查看
1, 结构的初始化:
2, 枚举的取值范围(CPP 97):
书上说的取值范围是: 先找到枚举量的最大值(如8), 再找到大于这个最大值的, 最小2的幂, 将它减去1(2^4-1 = 15), 这样就得到了取值范围的上限.
但是, 在G++和VS2012下测试, 无论是什么值(int的取值范围), 都是行的通的.
3, 指针与数组(CPP 108):
它们两个的区别之一是, 可以修改指针的值, 但数组名是常量.
下面是错误的用法:
另一个区别是, 对数组应用sizeof运算符得到的是数组的长度, 而指针应用sizeof得到的是指针的长度, 即使指针指向的是一个数组.
4, 数组的地址(CPP 109):
数组名被解释为其第一个元素的地址, 而对数组名应用地址运算符时, 得到是整个数组的地址.
声明这样一个指针如上, 如果省略括号, 优先级规则将使得pas先与[10]结合, 导致pas是一个short指针数组, 它包含10个元素, 因此括号是必不可少的.因此, pas的类型为short(*)[10].另外, 由于pas被置为&tell, 因此*pas与tell等价, 所以(*pas)[0]为tell数组的第一个元素.
这里详细描述一下strncpy和strncat 这两个函数(个人说明部分):
12345
123451234
以上strncpy的调用, 只是将第二个参数中的n(sizeof(buf) - 5)字符copy到buf, 而strncat的调用是将第二个参数的n(这里是buf的剩余空间)个字符加到buf中.
5, C++中复合语句的一条有趣的特性(CPP 137):
如果在语句块中定义一个新的变量, 则仅当程序执行该语句块中的语句时, 该变量在才在, 执行完该语句块后, 变量将被释放.
注意: 这条规则适用于复合语句, 并非是for循环的专属.
6, 字符函数库(CPP 177):
这个没什么重点, 只是如果平常如果需要的时候可以看一下, 而不用过多的编写已有的函数.
7, 函数和二维数组(CPP 224):
pas 等同于data
pas + 1等同于data + 1, pas为行首地址, pas + 1为第二行首地址, 表示整行
*(pas + 1)为元素地址, 为第二行第一个元素的地址.
**(pas + 1)为元素地址的值, 为第二行第一个元素的地址所存储的值.
*(*(pas + 2) + 2)为元素地址的值 , 为第三行第三个元素的地址所存储的值.
注意sum函数的签名, 不能定义为int **ar2,
**ar2表示一个int类型指针的指针, 即int * 的指针, 它还可以表示为指针数组, 如 int * p[10] 可以于 int **pa的形参匹配.
而int (*ar2)[4]表示一个ar2是一个指向一个4个int类型的数组的指针.
二维数组指针一定要给出第二维的宽度值.
而二维数组的指针也一定要给出表示二维数组第二维的宽度下标.
注意: 传递二维数组的数组名不能使用二级指针来接收他们, 类型是不匹配的.
8, 临时变量, 引用参数和const(CPP 262):
如果实参与引用参数不匹配, C++将生成临时变量.仅当数为const引用, C++才允许这样做.
什么时候将创建临时变量呢?如果引用参数是const, 则编译器将在下面两种情况下生成临时变量:
1) 实参的类型正确, 但不是左值.
2) 实参的类型不正确, 但可以转换为正确的类型.
这里主要注意一下左值的概念, 左值是可以被赋值的变量.
9, 函数的默认参数(CPP 275):
只有原型指定默认值. 函数定义与没有默认参数时完全相同.
就是说在声明函数的时候给定默认值, 在定义的时候不要加了, 否则编译会出错.
10, 模板函数, 常规模板, 具体化模板和实例化模板.
这里主要是要注意一下语法, 具体化模板是要给定针对某种类型的定义, 而实例化模板只是将实际类型的代入到函数声明中而以, 并不用重新给出定义.
在调用时, 也可以显示调用
Fun<int>('F');
这样的话将调用2#函数
编译器在调用时如果发现无法确定调用哪一个函数时, 将出现编译错误.
11, 关键字decltype(C++11)(CPP 295)
这是一个可以推断出的类型.
12, 说明符和限定符(CPP 317):
说明符:
auto 自动类型推断.
register 在现有的系统中, 以不在有效, 是否是用寄存器, 由操作系统决定.
extern 表明引用声明, 表示所引用的变量或是函数在其他地方文件中定义.
thread_local C++11指出变量的持续性与其所属线程的持续性相同.
mutable 该说明指出, 即使结构或类的对象声明为常对象, 但用mutable修饰过的变量, 也可以修改.
限定符:
const 常量
volatile 尽止编译器优化的变量
13, 链接性
链接性有 外部链接 即全局变量或函数. 在头文件中声明的对象(如果是在源文件中声明或定义的, 在其他文件中需要用extern声明引用一下)
内链接性 只有声明定义变量或函数的文件才能使用. 在文件中级经过static所修饰的对象.
无链接性 只有声明的域中才能使用, 无链接性只是用来指定变量. 在函数级中经过static修饰的对象
在全局范围的变量将会被初化始为默认值.而局部变量不会.
14, 定位new运算符(CPP 321):
使用new的定位操作方式, 不一定需要手动调用delete来释放, 因为定位的new操作可以分配到动态内存区也可能只是全局静态内存区,
想要定位需要事先定义一块有内存, 而该内存的作用域必需有效, 否则将出现预期以外的事情.
struct fish { int type; double weight; double length; }; typedef struct { int type; double w; double h; } cat; int main(int argc, std::string argv[]) { fish f = { 1, 8.0, 10.0 }; cat c = { 1, 10, 20 }; exit(0); }
2, 枚举的取值范围(CPP 97):
书上说的取值范围是: 先找到枚举量的最大值(如8), 再找到大于这个最大值的, 最小2的幂, 将它减去1(2^4-1 = 15), 这样就得到了取值范围的上限.
但是, 在G++和VS2012下测试, 无论是什么值(int的取值范围), 都是行的通的.
enum test_e { TYPE1 = 0, TYPE2 = 1, TYPE3 = 2, TYPE4 = 4 }; int main(int argc, std::string argv[]) { test_e e = (test_e)-800000; std::cout<<e<<std::endl; std::cin.get(); exit(0); }
3, 指针与数组(CPP 108):
它们两个的区别之一是, 可以修改指针的值, 但数组名是常量.
下面是错误的用法:
int arr[10] = {0}; int * p = arr; p += 3; arr += 3;
另一个区别是, 对数组应用sizeof运算符得到的是数组的长度, 而指针应用sizeof得到的是指针的长度, 即使指针指向的是一个数组.
4, 数组的地址(CPP 109):
数组名被解释为其第一个元素的地址, 而对数组名应用地址运算符时, 得到是整个数组的地址.
short tell[10]; std::cout<<tell<<std::endl; std::cout<<&tell<<std::endl; short (*pas)[10] = &tell;从数字上说, 这两个地址相同;但从概念上说, &tell(即tell)是一个2字节内存块的地址, 而&tell是一个20字节内存块的地址.因此, 表达式tell + 1将地址值加2, 而表达式&tell + 1将地址加20.(书上的印刷错误多的离谱).换句话说, tell是一个short指针(* short), 而&tell是一个指向包含10个元素的short数组的指针(short(*)[10]).
声明这样一个指针如上, 如果省略括号, 优先级规则将使得pas先与[10]结合, 导致pas是一个short指针数组, 它包含10个元素, 因此括号是必不可少的.因此, pas的类型为short(*)[10].另外, 由于pas被置为&tell, 因此*pas与tell等价, 所以(*pas)[0]为tell数组的第一个元素.
这里详细描述一下strncpy和strncat 这两个函数(个人说明部分):
char buf[10] = {0}; strncpy(buf, "1234567890", sizeof(buf) - 5); std::cout<<buf<<std::endl; strncat(buf, "1234567890", sizeof(buf) - strlen(buf) - 1); std::cout<<buf<<std::endl;输出为:
12345
123451234
以上strncpy的调用, 只是将第二个参数中的n(sizeof(buf) - 5)字符copy到buf, 而strncat的调用是将第二个参数的n(这里是buf的剩余空间)个字符加到buf中.
5, C++中复合语句的一条有趣的特性(CPP 137):
如果在语句块中定义一个新的变量, 则仅当程序执行该语句块中的语句时, 该变量在才在, 执行完该语句块后, 变量将被释放.
注意: 这条规则适用于复合语句, 并非是for循环的专属.
6, 字符函数库(CPP 177):
这个没什么重点, 只是如果平常如果需要的时候可以看一下, 而不用过多的编写已有的函数.
std::isalnum(c); //参数是否是字母或数字 std::isalpha(c); //参数是否是字母 std::iscntrl(c); //是否是控制符 std::isdigit(c); //是否是数字(0-9) std::isgraph(c); //是否是除空格之外的打印字符 std::islower(c); //是否是小写字母 std::isprint(c); //是否是打印字符(包括空格) std::ispunct(c); //是否是标点符号 std::isspace(c); //是否是空白字符, 如空格, 回车, 制表符, 换行符等. std::isupper(c); //是否是大写字母 std::isxdigit(c); //是否是16进制数 (1-9, abcdef) std::tolower(c); //如果c是大写, 则转成小写, 否则返回c std::toupper(c); //如果c是小写, 则转成大写, 否则返回c
7, 函数和二维数组(CPP 224):
int sum(int (*ar2)[4], int size) { int sum = 0; for (int i = 0; i < size; i++) for (int j = 0; j < 4; j++) sum += ar2[i][j]; return sum; } int main(int argc, std::string argv[]) { int data[3][4] = { { 1, 2, 3, 4 }, { 5, 6, 7, 8 }, { 9, 10, 11, 12 } }; std::cout<<sum(data, 3)<<std::endl; int (*pas)[4] = data; std::cout<<**pas<<std::endl; std::cin.get(); exit(0); }
pas 等同于data
pas + 1等同于data + 1, pas为行首地址, pas + 1为第二行首地址, 表示整行
*(pas + 1)为元素地址, 为第二行第一个元素的地址.
**(pas + 1)为元素地址的值, 为第二行第一个元素的地址所存储的值.
*(*(pas + 2) + 2)为元素地址的值 , 为第三行第三个元素的地址所存储的值.
注意sum函数的签名, 不能定义为int **ar2,
**ar2表示一个int类型指针的指针, 即int * 的指针, 它还可以表示为指针数组, 如 int * p[10] 可以于 int **pa的形参匹配.
而int (*ar2)[4]表示一个ar2是一个指向一个4个int类型的数组的指针.
二维数组指针一定要给出第二维的宽度值.
而二维数组的指针也一定要给出表示二维数组第二维的宽度下标.
注意: 传递二维数组的数组名不能使用二级指针来接收他们, 类型是不匹配的.
8, 临时变量, 引用参数和const(CPP 262):
如果实参与引用参数不匹配, C++将生成临时变量.仅当数为const引用, C++才允许这样做.
什么时候将创建临时变量呢?如果引用参数是const, 则编译器将在下面两种情况下生成临时变量:
1) 实参的类型正确, 但不是左值.
2) 实参的类型不正确, 但可以转换为正确的类型.
这里主要注意一下左值的概念, 左值是可以被赋值的变量.
9, 函数的默认参数(CPP 275):
只有原型指定默认值. 函数定义与没有默认参数时完全相同.
就是说在声明函数的时候给定默认值, 在定义的时候不要加了, 否则编译会出错.
10, 模板函数, 常规模板, 具体化模板和实例化模板.
这里主要是要注意一下语法, 具体化模板是要给定针对某种类型的定义, 而实例化模板只是将实际类型的代入到函数声明中而以, 并不用重新给出定义.
#include <iostream> //常规模板 1# template <typename T> void Fun(T a) { std::cout<<a + 1<<std::endl; } //实例化 2# template void Fun<int>(int a); //实例化 3# template void Fun(long a); //具体化 4# template<> void Fun(char c) { std::cout<<"Fun (char c)"<<std::endl; } //具体化 5# template<> void Fun<double>(double c) { std::cout<<"Fun (double)"<<std::endl; } int main(int argc, std::string argv[]) { Fun(10L); //3# Fun(10); //2# Fun(14.1F); //1# Fun(18.0); //5# Fun('F'); //6# std::cin.get(); exit(0); }
在调用时, 也可以显示调用
Fun<int>('F');
这样的话将调用2#函数
编译器在调用时如果发现无法确定调用哪一个函数时, 将出现编译错误.
11, 关键字decltype(C++11)(CPP 295)
这是一个可以推断出的类型.
template<class T1, class T2> auto Fun(T1 t1, T2 t2) -> decltype(t1 + t2) { decltype(t1 + t2) t3; return t3; }只有C++11.才支持这种语法.
12, 说明符和限定符(CPP 317):
说明符:
auto 自动类型推断.
register 在现有的系统中, 以不在有效, 是否是用寄存器, 由操作系统决定.
extern 表明引用声明, 表示所引用的变量或是函数在其他地方文件中定义.
thread_local C++11指出变量的持续性与其所属线程的持续性相同.
mutable 该说明指出, 即使结构或类的对象声明为常对象, 但用mutable修饰过的变量, 也可以修改.
限定符:
const 常量
volatile 尽止编译器优化的变量
13, 链接性
链接性有 外部链接 即全局变量或函数. 在头文件中声明的对象(如果是在源文件中声明或定义的, 在其他文件中需要用extern声明引用一下)
内链接性 只有声明定义变量或函数的文件才能使用. 在文件中级经过static所修饰的对象.
无链接性 只有声明的域中才能使用, 无链接性只是用来指定变量. 在函数级中经过static修饰的对象
在全局范围的变量将会被初化始为默认值.而局部变量不会.
14, 定位new运算符(CPP 321):
使用new的定位操作方式, 不一定需要手动调用delete来释放, 因为定位的new操作可以分配到动态内存区也可能只是全局静态内存区,
想要定位需要事先定义一块有内存, 而该内存的作用域必需有效, 否则将出现预期以外的事情.
#include <iostream> char buffer[1024]; int main(int argc, std::string argv[]) { int * p1 = new(buffer) int[10]; int * p2 = new(buffer + sizeof(int) * 10) int[20]; std::cout<<(int)&buffer<<std::endl; std::cout<<(int)p1<<std::endl; std::cout<<(int)p2<<std::endl; std::cin.get(); exit(0); }
相关文章推荐
- C++ Primer Plus(第6版)的技术点(2)
- C++ Primer Plus 第6版中文版 pdf下载
- 《C++ Primer Plus (第6版)》6.10 编程练习
- 【原创】一起学C++ 之enum ---------C++ primer plus(第6版)
- C++ Primer Plus第6版18个重点笔记
- C++ Primer Plus 第6版 中文版 清晰有书签PDF+源代码
- 《C++ Primer Plus (第6版)》2.7 编程练习
- c++ primer plus(第6版)中文版 第九章编程练习答案
- 【原创】一起学C++ 之 字符串 ---------C++ primer plus(第6版)
- c++ primer plus(第6版)中文版 第十一章编程练习答案
- [笔记] 《C++ Primer Plus(第6版)》
- 《C++ Primer Plus (第6版)》4.13 编程练习
- c++ primer plus(第6版)中文版 第三章编程练习答案
- 【原创】一起学C++ 之指针、数组、指针算术 ---------C++ primer plus(第6版)
- C++ Primer Plus(第6版) 第6章 编程练习
- 《C++ Primer Plus (第6版)》5.9 编程练习
- c++ primer plus(第6版)中文版 第五章编程练习答案
- c++ primer plus(第6版)中文版 第六章编程练习答案
- 【原创】一起学C++ 之指针的--/++ ---------C++ primer plus(第6版)
- 【原创】一起学C++ 之->(箭头符号) ---------C++ primer plus(第6版)