一、标准输入输出
cin是标准输入(istream对象)
cout是标准输出(ostream)
cerr是标准错误,用来输出警告和错误消息
clog用来输出程序运行时的一般性信息
二、 for 与 while 形式比较
在for循环中,循环控制变量的初始化和修改都放在语句头部分,形式较简洁,且特别适用于循环次数已知的情况。
在while循环中,循环控制变量的初始化一般放在while语句之前,循环控制变量的修改一般放在循环体中,形式上不如for语句简洁,但它比较适用于循环次数不易预知的情况(用某一条件控制循环)。
两种形式各有优点,但它们在功能上是等价的,可以相互转换。
三、读取数量不定的输入数据
while(cin>>value)
使用文件结束符Ctrl+Z结束输入。
四、选择类型的准则:
(0开头是八进制,0x开头是十六进制)
1. 当明确知道数值不可能为负时,选用无符号类型
2. 使用int执行整数运算,在实际应用中,short常常显得太小而long一般和int有一样的尺寸。所以一旦数值范围超过了int,即选用long long
3. 在算术表达式中不要使用char和bool,(类型char在一些机器上是有符号的,在另一些上可能没有符号)
如果要使用,请明确指明它的类型是signed char还是unsigned char
4. 执行浮点数运算时用double,long double一般是没有必要的
五、转义序列-----可使用泛化的转义序列
\n 换行符 \t 横向制表符 \a 报警(响铃)符 \v纵向制表符
\b 退格符 \“ 双引号 \\ 反斜线 \'单引号 \?问
\r 回车符 \f 进纸符
(使用不同的字符集,会有不同的表达方式)
六、什么是对象
对象是指一块能存储数据并具有某种类型的内存空间。
七、初始化
列表初始化:
形如
int units_sold = {0};
int units_sold{0};
称为列表初始化,是C++新11标准的一部分。
重要特点:如果我们使用列表初始化且初始值存在丢失信息的风险时,则编译器将报错。
默认初始化:
如果定义变量时没有指定初值,则变量被默认初始化,被赋予默认值。
内置类型的变量未被显式初始化的时候,其值由定义的位置决定。
1. 定义于任何函数体之外的变量被初始化为0;
2.定义在函数体内部的内置类型变量不被初始化。
八、变量声明和定义的关系
1. 声明使名字为程序所知; 定义负责创建与名字关联的实体。
2. 变量能且只能被定义一次,但是可以被多次声明。
3. 如果想声明一个变量而非定义它,就在变量名前添加关键字extern。在函数内部不能初始化一个由extern关键字标记的变量,会导致报错。
extern int i; //声明i而并非定义i
int j; //声明并定义j
4. 任何包含了显式初始化的声明即成为定义。(抵消extern的作用)
九、嵌套的作用域
1. 作用域能彼此包含,被包含(被嵌套)的作用域称为内层作用域,包含着别的作用域的作用域称为外层作用域。
2. 局部变量可覆盖全局变量。如果函数有可能用到某全局变量,则不再定义一个同名的局部变量。
3. 若函数中定义了与全局变量同名的局部变量后,还想要使用全局变量,则
cout<<::global<<enl;
若不加作用域操作符,则是使用局部变量。
十、引用和指针
1. 引用:为对象起了另一个名字(引用即别名)。引用类型引用另外一种类型。引用必须被初始化。即,改变都会改变,不论是对象本来的名字赋值变化还是引用别名进行赋值变化。
2. 指针:指针存放某个对象的地址,要想获得该地址,需要使用取地址符
int ival = 42;
int *p = &ival; //p存放变量ival的地址,或者说p是指向名为ival的int对象
为*p赋值实际上是为p所指的对象赋值。
3. 建议初始化所有指针。如果不清楚指针应该指向何处,就把他初始化为nullptr或0;
4. 任何非零指针对应的条件值都是true。
if (p) //p是否是空指针
if (*p) //p指向的对象是否是零
5. void* 指针是一种特殊的指针类型,可用于存放任意对象的地址。void* 指针能做的事情有限:
a)与别的指针比较
b)作为函数的输入输出
c)赋给另一个void*指针
不能直接操作void*指针所指的对象。
6. 指针和引用的区别
指针是一个任何其他类型的“指向”,而引用是对象的“另一个名称”。
区别:
a) 引用是已存在对象的另一个名称。指针本身就是一个对象。
b) 一旦初始化,引用就绑定到它的初始对象上,无法重新绑定引用以引用不同的对象。而指针可以重新分配或拷贝。
c) 引用必须初始化。指针在定义时可以不需要初始化。
d) 引用不能为NULL,指针可以为NULL。
7. **表示指向指针的指针,***表示指向指针的指针的指针,以此类推。
8. 有指向指针的引用。因为引用本身不是一个对象,所以不能定义指向引用的指针。例子如下:
int i = 42;
int *p;
int *&r = p //r是对指针p的一个引用,即别名
r = &i; //r是p的别名,故即为令p指向i
*r = 0; //解引用r,即将i的值改为0
十一、const限定符
1. const对象一旦创建后其值就不能再被修改,所以const对象必须初始化。初始值可以是任意复杂的表达式。只有const能够引用常量。
2. 如果想在多个文件之间共享const对象(这个情况是指const变量它的初始值不是一个常量表达式,但又确实有必要在文件之间共享。即只在一个文件中定义const,而在其他多个文件中声明并使用它),必须在变量的定义之前添加extern关键字。
3. const的引用:与普通引用不同的是,对常量的引用不能被用作修改它所绑定的对象。
4. 一般情况下,引用的类型必须与其所引用对象的类型一致。
例外情况:在初始化常量引用时,允许用任意表达式作为初始值,只要该表达式的结果能转换成引用的类型即可(隐式转换)。
5. 对const的引用可能引用一个并非const的对象。
6. 指向常量的指针。不能改变其所给对象的值,要想存放常量对象的地址,只能使用指向常量的指针。
const double pi = 3.14;
const double *cptr = π
7. const指针。指针是对象而引用不是,将指针本身定为常量。常量指针必须初始化,一旦初始化完成,则它的值(即存放在指针中的那个地址)就不能再改变了。
int errNumb = 0;
int *const curErr = &errNumb;
8. 顶层const:表示指针本身是个常量。可以表示任意的对象是常量,对任何数据类型都适用。拷贝操作是,拷入和拷出的对象是否是常量都没什么影响。
底层const:表示指针所指的对象是一个常量。执行对象的拷贝操作的时候,拷入和拷出的对象必须具有相同的底层const资格。
指针类型既可以是顶层也可以是底层。
const int *const p3 = p2; //靠右的const是顶层const,靠左的是底层const
const int &r = ci; //用于声明引用的const都使底层const
十二、 常量表达式与constexpr变量
1. 常量表达式:指值不会改变并且在编译过程就能得到计算结果的表达式。如常量值、用常量表达式初始化的const对象。(实际在一个复杂系统中,很难分辨一个初始值到底是不是常量表达式。故引用constexpr变量)
const int sz = get_size(); //sz不是常量表达式。
//尽管sz本身是一个常量,但它的具体值直到运行时才能获取到,所以也不是常量表达式
2. constexpr变量:C++11新标准规定,允许将变量声明为constexpr类型以便由编译器来验证变量是都是一个常量表达式。
声明为constexpr的变量一定是一个常量,而且必须用常量表达式初始化。
指针和引用都可以定义成constexpr类型,但是初始值受限。constexpr指针的初始值必须是nullptr或0或存储于某个固定地址中的对象。
const int *p = nullptr; //p是一个指向整型常量对象的指针
constexpr int *cp = nullptr; //np是一个指向整型的常量指针
字面值类型:算数类型、引用、指针……
十三、类型别名
1. typedef
typedef double wages; //wages是double的同义词
typedef wages base, *p; //base是double的同义词,p是double*的同义词
2. 别名声明
使用关键字using作为别名开始,其后紧跟别名和等号,其作用是把等号左侧的名字规定成等号右侧类型的别名。
using SI = Sales_item //ST是Sales_item的别名
3. auto
auto定义的变量必须有初始值
使用auto也能在一条语句中声明多个变量,但是必须保证该语句中所有变量的初始基本数据类型一样。
auto会忽略掉顶层const,如果需要推断出的auto类型是一个顶层const,那么需要明确指出
const auto f = ci
引用在auto上的初始化规则仍可以使用。
4. decltype类型指示符:选择并返回操作数的数据类型
在decltype的编译过程中,编译器仅分析表达式并得到它的类型,却不实际计算表达式的值。
decltype(f()) sum = x; //sum的类型就是函数f的返回类型
表达式中如果是解引用操作,那么结果类型就是引用类型。
decltype中的表达式如果是加上了括号的变量,结果将是引用。
decltype((p)) d; //错误,因为d的类型是引用,故必须初始化。
赋值也是能够产生引用的一类典型表达式,引用的类型就是左值的类型
int a = 3, b = 4;
decltype(a) c = a;
decltype(a = b) d = a; //d的类型是int&
//注意括号中的不实际计算,仅判断返回值类型
十四、预处理器
确保头文件多次包含仍能安全工作的常用技术是预处理器,它由C++语言从C语言继承而来。预处理器是在编译之前执行的一段程序,可以部分地改变我们所写的程序。
预处理指令:是以#开头的代码行,#号必须是该行除了任何空白字符外的第一个字符。
预编译处理指令:
#define 把一个名字设定为预处理变量,另外两个指令分别检查某个指定的预处理变量是否定义:
#ifdef 当且仅当变量已定义时为真。
#ifndef当且仅当变量未定义时为真。
一旦检查结果为真,则执行后续操作直到遇到#endif指令为止。。