常见的坑
int
,short
,long
,long long
都是带符号的,在前面添加unsigned
就能得到无符号类型。字符型被分为 3 种:
char
,signed char
,unsigned char
,前两种并不等价。 虽然有三种类型,但是实际上只有两种表现形式:有符号的和无符号的。有符号类型在与无符号类型运算时会隐式转换为无符号类型。
虽然变量初始化时候使用了
=
号,但是初始化和变量赋值并不相同。变量默认初始化:
变量类型 位置在函数内部 位置在函数外部 内置类型 undefined 0 自定义类型 由类决定 由类决定 #include <iostream> int default_initialize(int a) { // 输出必定是0 std::cout << a << std::endl; int b; return b; } int main() { int a; // 输出是随机值 std::cout << default_initialize(a) << std::endl; }
如果在函数体内部试图初始化一个
extern
标记的变量会引发错误。在嵌套作用域中,内层作用域中的定义可以覆盖外层作用域中声明的变量。
可以显式使用域操作符
::
来指明使用哪层的变量。
必须要理解的点
字面量的意思就是从这个表示形式就能推断其对应类型的量,不同表示形式的字面量和不同类型是多对一的关系。
变量的组成部分:类型和值。说白了就是一个定性一个定量。
类型决定变量在内存里面的存储方式,包括大小和布局方式,以及能参与的运算。
值在实际代码运行过程中则被各种函数使用参与运算。
变量声明和定义:
声明的意思就是:我要用这个变量。
定义的意思就是:我要对这个操作的变量做出定义,规定其具体的细节。
声明 定义 规定变量的类型和名字 ✅ ✅ 申请空间 ✅ 初始化 ✅ 执行多次 ✅ 用
extern
标记未初始化的变量来表明只对变量作声明:extern int i; //只声明不定义 int i; //声明并且定义 extern int i = 10; //声明并且定义
Q:为什么会有声明和定义这两个概念?
A:因为 C++支持分离式编译机制,这允许程序被分割成若干个文件,每个文件可以被独立编译。如果要在多个文件中使用同一个变量,就必须要将声明和定义分离。变量的定义必须且只能出现在一个文件中,其他用到这个变量的文件必须对其进行声明,且绝对不能进行重复定义。
名字的作用域:
同一个名字在不同的作用域中可以指向不同的实体。
名字的有效区域始于声明语句,以声明语句所在的作用域末端结束。
建议
明确数值不可能为负时使用
unsigned
类型。使用
int
执行整数运算,范围不够时使用long long
。使用
double
执行浮点数运算。算术表达式中不要使用
bool
和char
。避免写出依赖实现环境的代码,否则代码不可移植。
避免有符号类型和无符号类型之间的隐式类型转换。
C++11 中引入了列表初始化,例如:
// 传统的初始化方式 int units_sold = 0; int units_sold(0); // 现代的初始化方式 int units_sold{0}; int units_sold = {0};
列表初始化在用于内置类型变量时,如果初始值存在丢失信息的风险,编译器会报错。
long double pi = 3.1415926536; int a{pi}, b = {pi}; // 错误:没有执行类型转换,因为可能丢失信息 int a(pi), b = pi; // 正确:执行了隐式类型转化,丢失了信息
对每个内置类型的变量都执行显式默认初始化以防止 undefined 行为。
在变量第一次使用的地方进行定义操作。