声明:
- 文中内容收集整理自《C++ Primer 中文版 (第5版)》,版权归原书所有。
- 学习一门程序设计语言最好的方法就是练习编程。
1、8比特的char类型计算机表示的实际范围是-128-127。
2、赋值给无符号类型unsigned 时,如果超出它的显示范围,则结果是初始值对无符号类型表示数值总数取模后的余数。
如:unsigned char c = -1,则char占8比特,c的值是255。
赋值给带符号类型signed时,如果超出它的范围,结果是未定义的。此时可能继续工作、崩溃或者产生垃圾数据。
如:signed char c2 = 256 ,则char占8比特,c2的值是未定义的。
3、如果表达式里有带符号数和无符号类型,当带符号类型取值为负数时会出现异常结果。因为带符号数会自动转换成无符号数。
如:
unsigned u = 10;
int i = -42;
cout << u + i; //会输出一个很大的数 (2^32)
4、变量提供一个具名的、可供程序操作的存储空间,C++中每个变量都有它的数据类型。数据类型决定便佞所占内存空间的大小和布局方式,该空间能存储的值的范围,以及变量能参与的运算。C++中变量(variable)和对象(object)可以交换使用。
对象指的是一块能存储数据并具有某种类型的内存空间。
5、初始化不等于赋值。初始化是创建变量时赋予其一个初始值,而赋值的含义是把对象当前值擦除,而以一个新值代替。出于安全考虑,建议初始化每一个内置类型的变量。
6、C++语言支持分离式编译机制,该机制允许将程序分割为若干个文件,每个文件可被独立编译生成目标文件,最后将所有目标文件连接起来形成单一的可执行文件。
为了使用在其他文件中定义的变量,需要在当前文件中对将要使用的变量进行声明。声明使得名字为程序所知,一个文件如果想使用别处定义的名字则必须包含对那个名字的声明。而定义负责创建与名字关联的实体。
声明规定了变量的名字和类型,除此之外,定义还申请存储空间,也可能为变量赋一个初始值。
如果声明而不定义,则在变量名前加extern。
任何包含显式初始化的声明即成定义。
在函数体内部,如果试图初始化一个由extern关键字标记的变量将会引发错误。
extern int i; //声明
int j; //定义
extern int i = 10; //定义
变量能且仅能被定义一次,但可以被多次声明。
7、作用域:
名字有作用域,变量有生命周期
C++中的作用域有全局作用域和块作用域之分。
- 全局作用域:名字在整个程序范围内都可使用
- 块作用域:名字仅在部分范围内可用
作用域还可以嵌套。
名字的作用域始于名字的声明语句,以声明语句所在的作用域末端为结束
同一个名字在不同的作用域中可能指向不同的实体。
建议,在对象第一次被使用的地方附近定义它。也就是说越迟越好。
8、引用
区别于普通类型的变量,引用有以下几个特点:
- 引用只是别名,定义引用时,程序把引用和它的初始值绑定在一起
- 引用本身不是对象,编译器不会为引用分配内存空间,它只是一个别名
牢记以上两点就很容易理解引用了:
- 引用必须初始化(定义时要执行绑定的过程)引用的初始值必须是一个对象,而不能是字面值或者表达式。
- 对引用进行操作,实际是在操作引用绑定的对象(引用只是别名)
9、 指针
前面我们用&操作符进行引用的定义,它同时也是取地址符
int ival = 1024;
int *p = &ival; //p存放变量ival的地址,或者说p是指向变量ival的指针
&操作符取出变量ival的地址赋值给指针p
同样的,*操作符也具备两重身份,它同时也是解引用符
int i2 = *p;
对指针解引用得到的是指针所指的对象,如果给解引用的结果赋值,实际上也就是给指针所指的对象赋值。
对指针p解引用得到它所指的对象ival,然后ival的值用于初始化新定义的整型变量i2。
更复杂的情况:
int ival = 1024;
int *p = 0 //p合法,是一个空指针
int *pi = &ival; //pi是个合法指针,存放着ival的地址
int **ppi = π//ppi指向一个int型的指针
以及
int i = 42;
int *p; //p是个int型的指针
int *&r = p;//r是一个对指针p的引用
遇到这种复杂的情况时,我们可以使用从右向左阅读的方法
-
- 离变量名最近的符号对变量的类型有直接的影响,ppi是一个指针,r是一个引用
- 声明符的其余部分用来确定关联对象的类型,ppi指向的是一个指针,r引用的也是一个指针。
const对象的作用域
- 默认状态下,const对象仅在文件内有效
- 如果想要在多个文件中共享const对象,则需要在声明和定义时添加extern关键字
//file_1.cc, 定义 并初始化一个常量,该常量能被其他文件访问
extern const int bufSize = fcn();
//file_1.h 头文件
extern const int bufSize;//与file_1.cc中定义的bufSize是同一个
const的引用
可以把引用绑定到const对象上,称为对常用的引用,简称为常量引用
const int ci = 1024;
const int &r = ci;
13、 2.6自定义数据结构
头文件存在多次包含的情况(直接和间接),编译器会把头文件中的内容拷贝到包含文件中,而我们又要确保头文件中的内容不被多次定义。
确保头文件多次包含仍能安全工作的常用技术是预处理器(preprocessor)。
头文件保护符(header guard)
预处理变量有两种状态:
已定义的和未定义的。#define指令把一个名字设定为预处理变量。另外两个检查某个指定的预处理变量是否已定义。
#ifdef已定义时为真。#ifndef未定义时为真。#endif截止。
15、实现P64-P67的书店程序
头文件Sale_data.h://头文件只能定义和声明,不能赋值。赋值会报错。
#ifndef SALES_DATA_H #define SALES_DATA_H #include <string> struct Sales_data{ std::string bookNo; unsigned units_sold; double revenue; }; #endif // SALES_DATA_H_INCLUDED
源文件Sale_data.cpp:
1 #include<iostream> 2 #include<string> 3 #include"Sales_data.h" 4 5 int main(){ 6 7 Sales_data data1,data2; 8 double price = 0; 9 std::cin>>data1.bookNo>>data1.units_sold>>price;//读入第一本书的编号单价和数量 10 data1.revenue=data1.units_sold*price;//计算第一本书的收入 11 12 std::cin>>data2.bookNo>>data2.units_sold>>price;//读入第二本书的编号单价和数量 13 data2.revenue=data2.units_sold*price;//计算第二本书的收入 14 15 if(data1.bookNo == data2.bookNo){ 16 unsigned totalCnt = data1.units_sold + data2.units_sold; 17 double totalRevenue = data1.revenue + data2.revenue; 18 //输出 19 std::cout<<data1.bookNo<<" "<<totalCnt<<" "<<totalRevenue<<" "; 20 if(totalCnt) 21 std::cout<<totalRevenue/totalCnt<<std::endl; 22 else 23 std::cout<<"(no sales)"<<std::endl; 24 return 0; 25 }else{ 26 std::cerr<<"Data must refer to the same ISBN"<<std::endl; 27 return -1; 28 } 29 30 }
输入两个交易记录:
0-201-78345-x 3 20.00
0-201-78345-x 2 25.00