变量


字面常数存储于内存,现在的问题是若要将数值存储在内存,并在稍后取回使用,该如何进行?

变量(Variable)提供一个有名称的内存存储空间,变量可包含的信息包含变量数据类型、变量内存地址与变量存储值;C++ 开发者也常用对象(object)这个名称来表示变量,因为对象对 C++ 开发者来说,不只是表示类实例之类的东西,而是代表着一块内存局部,可能含有类型与值等信息。

在 C++ 中要使用变量,必须先定义变量名称与数据类型,例如:

int age;            // 定义一个整数变量
double money;      // 定义一个倍精度浮点数变量

C++ 使用intfloatdoublecharbool等定义变量名称与类型,变量命名时不可以使用数字作为开头,也不可以使用一些特殊字符,像是 *&^% 之类的字符,变量名称不可以与 C++ 内定的关键字同名,例如intfloatclass等等。

在 C++ 定义变量,会配置一块内存空间,空间长度依定义时的数据类型而定,如果在函数外定义变量,变量会默认为对应类型的空值,若是在函数中定义变量,被配置的这块空间中原先可能就有数据,也因此变量在定义后的值是不可预期的,应该在在变量定义后初始化其值,可以使用「指定运算符」(Assignment operator)=来指定变量的值,例如:

int ageForStudent = 0;
double scoreForStudent = 0.0;
char levelForStudent = 'A';

上例中三个变量分别被初始化为00.0'A',还可以使用隐喻的方式来定义变量并指定初值,例如:

int ageForStudent(0);
double scoreForStudent(0.0);
char levelForStudent('A');

这两种定义方式在定义变量的时候,同时指定变量的存储值,字符在指定时需使用单实参''包括,在定义并指定变量值之后,可以使用变量名称来获取其所存储的值,下面这个程序是个简单的示范:

#include <iostream> 
using namespace std; 

int main() { 
    int ageForStudent; 
    double scoreForStudent; 
    char levelForStudent; 

    cout << "\n年级\t得分\t等级"; 
    cout << "\n" << ageForStudent 
         << "\t" << scoreForStudent 
         << "\t" << levelForStudent 
         << "\n"; 

    ageForStudent = 5; 
    scoreForStudent = 80.0; 
    levelForStudent = 'B'; 

    cout << "\n年级\t得分\t等级"; 
    cout << "\n" << ageForStudent 
         << "\t" << scoreForStudent 
         << "\t" << levelForStudent 
         << "\n"; 

    return 0;
}

这个程序先定义变量,但没有初始化其值,第一次显示时会出现不可预期的数据,而在指定变量的值之后,显示变量值时就会出现指定的数据了,执行结果如下所示:

年级    得分    等级
4200459 1.55553e-306

年级    得分    等级
5       80      B

也可以在使用定义变量后,使用以下的构造子(Constructor)方式将变量的值初始化为各类型的空值:

int ageForStudent = int();
double scoreForStudent = double();
char levelForStudent = char();

在 C++ 11 中,增加了清单初始化化(list initialization),其目的在统一初始化化的方式,对于基本类型,也可以使用同一种风格来初始化化。

int ageForStudent{0};
double scoreForStudent{0.0};
char levelForStudent{'A'};

这种初始化化还有个特性,{}中的值若指定给变量时,有可能造成精度遗失的话,编译器会提出警讯。例如:

double pi = 3.14159;
int x = {pi};  // warning: narrowing conversion of 'pi' from 'double' to 'int' inside { }

如果如下编写,默认是不会提出警讯的:

double pi = 3.14159;
int x = pi;

这是因为类型发生了隐式转换(implicit conversion),pi的小数会被截去,整数部份被指定给x,若在这种情况下,也想要编译器提出警讯,编译时可以加上-Wconversion实参。

可以在定义变量时使用const关键字来限定,如果程序中有其他代码试图改变这个变量,编译器会检查出这个错误,例如:

const double PI = 3.14159;
PI = 3.14;

这一段代码中的MAX变量我们使用const来限定,所以它在指定为 10 之后,就不可以再指定值给它,所以第二次指定会被编译器指出错误,在 g++ 编译器时会出现这样的错误消息:

error: assignment of read-only variable 'PI'

使用const来限定的变量,目的通常就是不希望其它代码来变动值,例如圆周率 PI 的指定。

从 C++ 11 开始,可以使用constexpr请编译器验证常数初始化时是在编译时期决定,例如:

constexpr int A = 10;
constexpr int B = sizeof(10);
constexpr int C = sizeof(B);
constexpr int D = rand();    // error: call to non-'constexpr' function 'int rand()'

rand返回随机乱数,因此D的实际值要在执行时期才能决定,而非编译时期,因此发生错误;constexpr的价值在于,在重重的表达式或函数调用下,编译时期常数有时很难一眼看出,这时加上constexpr请编译器来进行检验就方便多了。

如果要定义无符号整数变量,可以加上unsigned关键字,例如:

unsigned int i ;

bool类型的变量虽然也可视为整数类型,但不能在定义变量时加上unsigned来修饰。

从 C++ 11 开始,若变量定义后有明确地初始化化,可以使用auto让编译器推断变量类型,例如:

int ageForStudent = 5; 
double scoreForStudent = 80.0; 
char levelForStudent = 'B';

可以改为:

auto ageForStudent = 5; 
auto scoreForStudent = 80.0; 
auto levelForStudent = 'B';

只用auto却没有初始化,会发生编译错误:

auto ageForStudent; // error: declaration of 'auto ageForStudent' has no initializer




展开阅读全文