C++primer5th笔记-创新互联

目录
  • 2022年11月25日 周五 阴
    • 第一、二章:变量和基本类型
      • 基本内置类型
        • unsigned
        • float与double
        • 'A'与"A"
        • 布尔类型转换时
        • 初始化与赋值
        • 初始化
        • 声明与定义
      • 复合类型
        • 引用与指针
        • 指向指针的指针
        • 指向指针的引用
  • 2022-11-26 星期六 小雨
      • const
    • 第三章 字符串、常量和数组
      • 命名空间
      • string
      • vector
      • 迭代器
  • 2022-11-27 星期日 小雨
      • 数组
        • 指针和数组
        • 多维数组
    • 第四章:表达式
      • 算术运算符
        • 成员访问运算符
  • 2022-11-28 周一 阴
      • 位运算
        • sizeof
        • 类型转换
      • 第五章: 语句
    • 第六章:函数
        • 函数基础
        • 数组形参
        • 构造函数
    • 2022年11月30日 周三 雪
      • 第九章:顺序容器
        • 迭代器

创新互联于2013年创立,先为隆化等服务建站,隆化等地企业,进行企业商务咨询服务。为隆化企业网站制作PC+手机+微官网三网同步一站式服务解决您的所有建站问题。2022年11月25日 周五 阴 第一、二章:变量和基本类型 基本内置类型 unsigned

除去布尔型和扩展的字符型外,其他整型可以划分为带符号的和无符号的两种。带符号类型可以表示正数、负数或0,无符号类型则仅能表示大于等于0的值。

如果表达式里既有带符号类型又有无符号类型,当这个带符号类型取值为负时会出现异常,因为带符号数会自动转换成无符号数。所以切勿混用带符号与无符号类型。
unsigned u = 10, u2 = 42 ,u - u2 = 4294967264
10, 10u, 10L, 10uL, 012, 0xC:整形字面值,无符号整形字面值,长整形字面值,无符号长整形字面值,八进制整形字面值,十六进制整形字面值;
int month = 09, day = 07; 八进制整形,八进制中没有9,所以会报错。
1024f;非法,整形字面值不可加后缀f;

float与double

float最小尺寸为6位有效值,double最小尺寸为10位有效值。

'A’与"A"

前者代表单独的字符A
==※==后者代表了一个字符的数组,包含两个字符:一个是字母A,另一个是空字符(‘\0’)

布尔类型转换时

非布尔类型值赋给布尔类型值时,初始值为0,结果为false。除此之外为true
布尔类型值赋给非布尔类型值时,初始值为false,结果为0。初始值true,结果为1

初始化与赋值

初始化不是赋值
初始化:创建变量时赋予其一个初始值
赋值:把对象的当前值擦除,用一个新的值来替代

初始化

定义于函数体内的内置类型的对象如果没有初始化,则其值未定义,如果试图拷贝或者访问此类值将引发错误。(所以建议初始化每一个内置类型的变量)
而类的对象如果没有显式地初始化,则其值由类决定。(例如string类如果没有指定初值则生成一个空串)

int i = { 3.14 }; 非法,不能执行强制转换,因为存在丢失信息的风险
int i = 3.14;合法,已强制转换。

声明与定义

声明规定了变量的类型和名字,定义不仅这样,还会申请存储空间,也有可能直接赋初始值。

extern int i;	//声明i,但无定义(如果赋初始值就是定义了)
int j; 			// 声明并定义j

变量能被多次声明,但只能被定义一次

含义是在编译阶段检查类型

用户自定义的类名一般以大写字母开头 Sales_item

一旦定义了引用,就无法令其再绑定到另外的对象

复合类型 引用与指针

引用是其他对象的别名。指针本身就是对象(所以它本身也有自己的地址),存放其他对象的地址
因为引用不是对象,没有实际地址,所以不能定义指向引用的指针

int *p1 = nullptr;  int *p1 = NULL; //等价于int *p1 = 0
int *p1 = 0;  //直接将p1初始化为字面常量0来生成空指针

推荐使用nullptr

pi = &ival;//pi的值被改变,此时pi里是ival的地址,pi指向了ival
*pi = 0; //ival的值被改变,指针pi并没有改变

任何非0指针对应的bool都是true;if(pi)
建议 int *p这种写法

指向指针的指针
int  ival = 1024;
int *pi = &ival;
int **ppi = π

遇到复杂的指针和引用时,建议从右向左阅读

指向指针的引用
int i = 42;
int *p;
int *&r = p;// r是一个对指针p的引用

r = &i;// 因为r是引用了一个指针,所以给r赋值&i就是令p指向i
*r = 0; // 解引用r得到i,将i的值改为0;

为什么没有指向引用的指针?因为引用本身就不是一个对象。

2022-11-26 星期六 小雨 const

const对象一旦创建后其值就不能再改变,所以const对象必须初始化
如果想在多个文件之间共享const对象,就必须在变量的定义之前加extern关键字

int errNumb = 0;
int *const curErr = &errNumb; // curErr将一直指向errNumb(此时可以通过指针修改errNumb的值)
const double pi = 3.14;
const double *const pip = π	// pip是一个指向常量对象的常量指针(都不可修改)
const int *p;	//合法,指向常量的指针可以不初始化。
onst int *const p3;	//不合法,常量指针未初始化;
第三章 字符串、常量和数组 命名空间

操作符(::)的意思是:编译器应从操作符左侧名字所示的作用域中寻找右侧那个名字
头文件里的内容会拷贝到所有引用它的文件中,所有应该避免在头文件中使用using声明

string

在用cin读取string对象时,会自动忽略开头的空白,并在下一个空白处停止
如果输入" Hello World “,那么输出将是"Hello”
要解决这个问题可以使用getline(cin, s),当遇见换行符时停止

string中的size()函数返回的其实是一个unsigned无符号的int值。所以,对于表达式s.size()< n来说,如果n是一个负值,则这个表达式的结果几乎100%是true,因为负值n会自动转换成一个比较大的无符号值。
所以如果一个表达式里已经有了size()函数就不要再使用int了,这样可以避免混用int和unsigned可能带来的问题
C++中,字符串字面值与string是不同的类型,string s = “hello” + ","是错误的。必须保证每个加号两侧的运算对象至少有一个是string。

不管什么时候,只要对string对象使用了下标,都要确认这个下标处有值
小tips:

for (decltype(s.size()) index=0;  index != s.size(); index++ ) {}

题目:

string s;
cout<< s[0]<< endl;
//合法,定义后就占用一个字节,包含’\0’。
vector

vector中只能存放同一种类型对象
vector不能存放引用,因为引用不是对象

vectorv1(10, 1);	// 有10个元素,每个值都是1
vectorv1{10, 1};	// 有2个元素,分别是10,1
vectorsvec(10, "null");	//正确,创建了一个包含10个元素为“null”的vector对象。

范围for语句体内不应改变其所遍历序列的大小

只能对已确认存在的元素执行下标操作(否则常常会出现缓冲区溢出buffer overflow)

迭代器

begin成员指向容器中第一个元素,而end返回容器尾元素的后一个元素(即不存在的元素)
当容器为空时,begin和end返回的是同一个迭代器,即尾后迭代器

2022-11-27 星期日 小雨 数组

要理解数组声明的含义,最好是从数组的名字开始,由内向外依次阅读
int ia[txt_size()]; 当txt_size()是constexpr时正确;否则错误

string sa[10];
int ia[10];
int main() {string sa2[10];
    int ia2[10];
}

sa:空字符串;
ia:0;
sa2:空字符串;
ia2:不确定值。

指针和数组
string nums[] = {"one", "two", "three"};
string *p = &nums[0];
string *p2 = nums;	//等价于 p2 = &nums[0]
// 	通常情况下,使用数组类型的对象其实是使用一个指向该数组首元素的指针

使用数组类型的对象,其实就是使用一个指向该数组首元素的指针

int ia[] = {0, 1, 2, 3, 4};
auto ia2(ia);	// ia2是一个整型指针,指向ia的第一个元素
但是如果使用decltype时转换不会发生、
decltype(ia) ia3 = {0, 1, 2, 3, 4};	//此时ia3是一个含有5个整数的数组

要特别注意:尾后指针不能执行解引用和递增操作

C++程序应该尽量使用vector和迭代器,而避免使用内置数组和指针
应该尽量使用string,而避免使用C风格的基于数组的字符串

多维数组

严格地说,C++中并没有多维数组,只有数组的数组。
int ia[3][4]; //大小为3的数组,每个元素是含有4个整数的数组
使用for循环多维数组时,除最内层循环外,其他循环的控制变量应该为引用类型(否则可能会出现转换为指向数组首元素指针的情况)

int ia[3][4];	//大小为3的数组,其中每个元素都是含有4个整数的数组
int (*p)[4] = ia;	//	p指向含有4个整数的数组
p = &ia[2];	// p指向ia的尾元素

int *ip[4];	//	整型指针的数组
int (*ip)[4];	//指向含有4个整数的数组
第四章:表达式 算术运算符

当优先级相同时,按照从左向右的顺序组合

bool b = true;
bool c = -b;	// c依旧是true;因为b参与运算后值被转为1,而-1不等于0,所以转为bool后为true

参与取模运算%的运算对象必须为整数类型

const char *cp = "Hello World";
if (cp && *cp)
当指针cp不为空时,才判断解引用cp的值。
我们知道,cp不为空,&&左侧为true;*cp为’H’,右侧也为真,所以if语句为真。

避免使用后置递增/递减,因为后置版本需要将原始值存储起来以便于返回这个未修改的内容

成员访问运算符

解引用运算符的优先级低于点运算符

ptr->men 等价于 (*ptr).men;
2022-11-28 周一 阴 位运算

强烈建议仅将位运算符用于处理无符号类型
左移运算符<< 在右侧插入值为0的二进制位
右移运算符 >>行为取决于左侧运算对象的类型
如果是无符号型,在左侧插入值为0的二进制位
如果是带符号型,在左侧插入值为0的二进制位或插入符号位的副本
位求反运算符 `:0置1,1置0
位异或运算符^:两个中只有1个1则为1,否则为0

cout<< 10< 42;	//错误,试图比较cout和42!
sizeof
sizeof(obj);	//这种情况返回存储obj所占空间的大小
sizeof obj;		//这种情况返回obj类型 所占空间的大小
int x[10];   int *p = x;
cout<< sizeof(x)/sizeof(*x)<< endl;	// 40/4=10,数组所占的字节数/数组类型int所占的字节数,就是数组的个数;
cout<< sizeof(p)/sizeof(*p)<< endl;	// 4/4=1,指针所占的字节数/int所占的字节数。
类型转换
int val = 3.14 + 3;	//	3会转换为double,然后执行浮点数加法运算,再将double转为int赋予val
3.1415L + 'a';	// 'a'提升为int,然后int转为long double
cval + fval;	// cval提升为int,然后int转为float
fval = ui - ival * 1.0;	//	ival->double,ui->double,double->float;

强烈建议避免强制类型转换

第五章: 语句

在switch中,哪怕default没用,也最好加上
鲁棒是Robust的音译,也就是健壮和强壮的意思。它也是在异常和危险情况下系统生存的能力。

第六章:函数 函数基础

局部静态对象:即使其所在的函数执行结束对它也没有影响,它直到程序终止才被销毁。
在C++中,建议使用引用类型的形参代替指针类型的形参。而且,当函数无需改变引用形参的值时,最好将形参声明为常量引用

const int &r = 42;	//正确
int &r = 42;	// 错误,不能用字面值初始化一个非常量引用
char *argv[];等同于 char **argv;

不要返回局部对象的引用或指针
如果main函数结尾处没有return语句,编译器将隐式地插入一条返回0的return语句
重载:名字相同,形参列表不同

数组形参
void print(const int*);
void print(const int[]);
void print(const int[10]);
// 这三者等价,而[10]只是表示我们期望数组含有多少元素,实际不一定

通常应该在函数声明中指定默认实参,并将该声明放在头文件中

构造函数

无论何时,只要类的对象被创建,就会执行构造函数
struct 于class的区别

2022年11月30日 周三 雪 第九章:顺序容器
vector:	可变大小数组。访问快,在尾部之外位置插入/删除元素慢
deque:双端队列。访问快,在头尾位置插入/删除元素快
list: 双向链表。只支持双向的顺序访问。任何位置插入/删除都很快
forward_list: 单向链表。只能单向顺序访问。在任何位置插入/删除都很快
array:固定大小数组。访问快,不能添加/删除元素
string:与vector基本一样,但只能保存字符。访问快,在尾部插入/删除快
通常情况下,使用vector是最好的选择
如果要求随机访问元素:vector或deque
如果要求在中间插入/删除元素:list或forward_list
如果要求在头尾插入/删除元素且不在中间位置插入/删除元素:deque
迭代器

迭代器范围:左闭右开
向一个vector、string或deque插入元素会使所有指向容器的迭代器、引用和指针失效
调用swap后,元素本身并未交换,也就意味着指向容器的迭代器、引用和指针都依然有效(除string外)
每次改变容器的操作之后都应该重新定位迭代器,特别是vector、string和deque;

你是否还在寻找稳定的海外服务器提供商?创新互联www.cdcxhl.cn海外机房具备T级流量清洗系统配攻击溯源,准确流量调度确保服务器高可用性,企业级服务器适合批量采购,新人活动首月15元起,快前往官网查看详情吧


名称栏目:C++primer5th笔记-创新互联
网页网址:http://scyanting.com/article/cdjsic.html