1. 什么是变量
1.1 声明变量以访问和使用内存
- 变量类型向编译器指出了变量可存储的数据的性质,编译器将为变量预留必要的空间
- 变量名由程序员选择,它替代了变量值在内存中的存储地址
- 变量名可包含数字和字母,但不能以数字打头。变量名不能包含空格和算术运算符(+、-等)。另外,变量名不能是保留的关键字。例如,将变量命名为 return 将导致程序无法通过编译。变量名可包含下划线(_),这种字符经常包含在描述性变量名中
- 除非给变量赋初值,否则无法确保相应内存单元的内容是什么
#include <iostream>
using namespace std;
int main () {
cout << "Enter the first number: ";
int firstNumber = 0;
cin >> firstNumber;
cout << "Enter the second number: ";
int secondNumber = 0;
cin >> secondNumber;
int multiplicationResult = firstNumber * secondNumber;
cout << firstNumber << " x " << secondNumber;
cout << " = " << multiplicationResult << endl;
return 0;
}
1.2 声明并初始化多个类型相同的变量
- C++中可同时声明多个类型相同的变量
- 在C++中可在需要时再声明变量,这让代码更容易理解
int firstNumber = 0, secondNumber = 0, multiplicationResult = 0;
1.3 理解变量的作用域
-
常规变量(如前面定义的所有变量)的作用域很明确,只能在作用域内使用它们,如果在作用域外使用它们,编译器将无法识别,导致程序无法通过编译
-
编译器将main( )中声明的变量视为独立的实体,即便它们与另一个函数中声明的变量同名,因为这些变量的作用域不同
1.4 全局变量
- 在函数外定义的变量称之为全局变量,其作用域为从定义处开始到定义该全局变量的源文件结束处
- 除非有必要,否则不建议使用全局变量,因为全局变量增大了程序的存储空间、降低了函数通用性、增加了函数理解的复杂度
- 在同一个源文件中,若全局变量与局部变量同名,那么在局部变量作用域内,全局变量不起作用
1.5 命名约定
- 对于变量名,采用骆驼拼写法
- 变量名firstNumber、secondNumber 和multiplicationResult 中,第一个单词的首字母采用小写,这被称为骆驼拼写法
- 对于函数名等其他元素,采用Pascal 拼写法
- 在函数名MultiplyNumbers()中,每个单词的首字母都大写,这被称为Pascal 拼写法
2. 编译器支持的常见C++变量类型
- 使用bool 变量存储布尔值
bool alwaysOnTop = false; // 1为true;其他为false
- 使用char 变量存储字符
// char 变量用于存储单个字符
char userInput = 'Y'; // 初始化char为'Y'
-
有符号整数和无符号整数的概念
- 符号表示正或负。在计算机中使用的所有数字都以位和字节的方式存储在内存中。1字节的内存单元包含8位,每位都要么为0,要么为1(即存储这两个值之一),因此1字节的内存单元可以有2^8 (即256)个不同的取值。同样,16位的内存单元可以有2^16(65536)个不同的取值。
- 如果这些取值是无符号的(即为正数),则1个字节的可能取值为0~255,而2 个字节的可能取值为0~65535。
- 占用8 位的有符号数的取值范围为−127~127,而占用16 位的有符号数的取值范围为−32768~32768。
-
有符号整型short、int、long 和long long
- int 可能是使用得最多的类型,在大多数编译器中,其长度都是32 位。应根据变量可能存储的最大值给它指定合适的类型。
-
无符号整型unsigned short、unsigned int、unsigned long 和 unsigned long long
- 它们的最大取值为相应有符号类型的两倍
- 如果预期变量的取值不会为负数,就应将其类型声明为无符号的
-
选择正确的数据类型以免发生溢出错误
- 就拿unsigned short 来说吧,它占用16 位内存,因此取值范围为0~65535。usigned short 变量的值为65535 后,如果再加1,将导致溢出,结果为0
- 数据类型short 的取值范围为−32768~32768,如果这种变量的值已经是32768,则将其加1的结果为最小的负数
-
浮点类型float 和double
- 浮点数就是实数,可以是正,也可以是负,还可以包含小数值
- C++14 新增了用单引号表示的组块分隔符。使用这种分隔符可提高代码的可读性,如下面的初始化语句所示:
-
int moneyInBank = -70'000; // -70000 double pi = 3.141'592'653'59; // 3.14159265359
3. 使用sizeof确定变量的长度
- 获悉标准C++变量类型的长度
#include <iostream>
int main() {
using namespace std;
cout << "Size of bool: " << sizeof(bool) << endl;
cout << "Size of char: " << sizeof(char) << endl;
cout << "Size of unsigned short int: " << sizeof(unsigned short) << endl;
cout << "Size of short int: " << sizeof(short) << endl;
cout << "Size of unsigned long int: " << sizeof(unsigned long) << endl;
cout << "Size of long: " << sizeof(long) << endl;
cout << "Size of int: " << sizeof(int) << endl;
cout << "Size of unsigned long long: "<< sizeof(unsigned long long)<< endl;
cout << "Size of long long: " << sizeof(long long) << endl;
cout << "Size of unsigned int: " << sizeof(unsigned int) << endl;
cout << "Size of float: " << sizeof(float) << endl;
cout << "Size of double: " << sizeof(double) << endl;
return 0;
}
Size of bool: 1
Size of char: 1
Size of unsigned short int: 2
Size of short int: 2
Size of unsigned long int: 4
Size of long: 4
Size of int: 4
Size of unsigned long long: 8
Size of long long: 8
Size of unsigned int: 4
Size of float: 4
Size of double: 8
- C++11 引入了固定宽度的整型,让您能够以位为单位指定整数的宽度
- 这些类型为int8_t和unit8_t,分别用于存储8位的有符号和无符号整数;还可能使用16位、32位和64位的整型,它们为int16_t、uint16_t、int32_t、uint32_t、int64_t和uint64_t
- 要使用这些类型,必须包含头文件
-
#include <cstdint>
-
4. 使用auto自动推断类型
- 让编译器去决定变量的类型,而编译器将根据初始值来确定合适的类型
- 使用auto时必须对变量进行初始化,因为编译器需要根据初始值来确定变量的类型
#include <iostream>
using namespace std;
int main() {
auto coinFlippedHeads = true;
auto largeNumber = 2500000000000;
cout << "coinFlippedHeads = " << coinFlippedHeads;
cout << " , sizeof(coinFlippedHeads) = " << sizeof(coinFlippedHeads) << endl;
cout << "largeNumber = " << largeNumber;
cout << " , sizeof(largeNumber) = " << sizeof(largeNumber) << endl;
return 0;
}
5. 使用typedef替换变量类型
- C++允许您将变量类型替换为您认为方便的名称,为此可使用关键字typedef
typedef unsigned int STRICTLY_POSITIVE_INTEGER;
STRICTLY_POSITIVE_INTEGER numEggsInBasket = 4532;
6. 声明是常量
-
在C++中,常量可以是:
- 字面常量
- 使用关键字const声明的常量
- 使用关键字constexpr声明的常量表达式(C++11 新增的)
- 使用关键字enum声明的枚举常量
- 使用#define定义的常量(已摒弃,不推荐)
-
字面常量
- 字面常量可以是任何类型:布尔型、整型、字符串等
-
std::cout << "Hello World" << std::endl; // Hello World 就是一个字符串字面常量 int someNumber = 10; // 10是不可修改的,因此也是字面常量 int someNumber = 0b1010; // 从C++14 起,还可使用二进制字面量
-
使用const将变量声明为常量
#include <iostream>
int main() {
using namespace std;
const double pi = 22.0 / 7;
cout << "The value of constant pi is: " << pi << endl;
return 0;
}
- 使用constexpr定义常量表达式
// 常量表达式必须包含简单的实现,并返回简单类型,如整数、双精度浮点数等
// C++14中,常量表达式可包含决策结构,如if和switch语句
// 在C++编译器中,都通过常量M_PI提供pi值,但必须包含头文件<cmath>
#include <iostream>
constexpr double GetPi() { // 通过关键字constexpr,可让常量声明像函数
return 22.0 / 7;
}
constexpr double TwicePi() { // 在一个常量表达式中,可使用另一个常量表达式
return 2 * GetPi();
}
int main() {
using namespace std;
const double pi = 22.0 / 7;
cout << "constant pi contains value " << pi << endl;
cout << "constexpr GetPi() returns value " << GetPi() << endl;
cout << "constexpr TwicePi() returns value " << TwicePi() << endl;
return 0;
}
- 枚举
- 可使用关键字enum来声明枚举
- 枚举由一组称为枚举量的常量组成
- 编译器将枚举量转换为整数,每个枚举量都比前一个大1。您可以指定起始值,如果没有指定,编译器认为起始值为0
// 使用枚举量指示基本方位
enum CardinalDirections
{
North = 25,
South,
East,
West
};
- 使用#define定义常量
// 预处理器将进行文本替换,而不是智能替换
// 使用#define 定义常量的做法已被摒弃,因此不应采用这种做法
#define pi 3.14286 // #define 是一个预处理器宏
Q&A
- 既然可以使用常规变量代替常量,为何还要定义常量?
- 通过声明常量(尤其是使用关键字const 时),可告诉编译器,其值是固定的,不允许修改。这样,编译器将确保不给常量赋值,即便另一位程序员接手了您的工作,不小心试图覆盖常量的值。因此,在知道变量的值不应改变时,应将其声明为常量,这是一个不错的编程习惯,可提高应用程序的质量。
- 为何应给变量赋初值?
- 如果不初始化,就无法知道变量包含的初始值。在这种情况下,初始值将是给变量预留的内存单元的内容。下面的语句使得创建变量myFavoriteNumber 后,就将指定的初始值0 写入到为该变量预留的内存单元:
int myFavoriteNumber = 0;
有时候,需要根据变量的值(通常是核实它不为零)做条件处理,如果不对变量进行初始化,这样的逻辑将不可靠,因为未赋值或初始化的情况下,程序员通过选择合适的变量类型,可节省内存并提高速度。如果编写的是常规台式机或高端智能手机程序,选择不同整型带来的性能提升或内存节省将很小,有时甚至可以忽略不计。
- 如果不初始化,就无法知道变量包含的初始值。在这种情况下,初始值将是给变量预留的内存单元的内容。下面的语句使得创建变量myFavoriteNumber 后,就将指定的初始值0 写入到为该变量预留的内存单元: