前言
变量提供一个具名的、可供程序操作的存储空间。C++中的每个变量都有其数据类型,数据类型决定着变量所占内存空间的大小和布局方式、该空间能存储的值的范围,以及变量能参与的运算。对C++程序员来说,“变量(variable)”和“对象(object)”一般可以交换使用
一、变量定义
变量定义的基本形式是:首先是类型说明符(type specifier),随后紧跟着由一个或多个变量名组成的列表,其中变量名以逗号分隔,最后以分号结束。
代码如下(示例):
int sum = 0, value, units_sold=0; //sum、value和units_sold都是int,其中sum和units_sold初值为0
Sales_item item; //item的类型是Sales_item(类)
string book("0-201"); //String是一个类库,表示一个可变长的字符序列,book通过一个string字面值初始化
二、初始值
1.什么是对象?
C++程序员们在很多场合都会使用对象(object)这个名词。通常情况下,对象是指一块能存储数据并具有某种类型的内存空间。不过一般仅有在与类有关的场景下才使用“对象”这个词。
代码如下(示例):
#include<iostream>
#include<test.h> //引入test.h头文件
using namespace std;
int main(void)
{
int p1; //p1既可以叫变量,也可以叫对象(一般叫变量p1)
test p2; //一般与类有关的叫对象p2
return 0;
}
2.初始化
当对象在创建时获得了一个特定的值,我们说这个对象被初始化了(initialized)了。用于初始化变量的值可以是任意复杂的表达式。当一次定义了两个或多个变量时,对象的名字随着定义也就马上可以使用了。因此在同一条定义语句中,可以用先定义的变量值去初始化定义的其他变量。
代码如下(示例):
#include<iostream>
using namespace std;
int main(void)
{
//正确:price先被定义并赋值,随后被用于初始化discount,即discount=109.99*0.16
double price = 109.99, discount = price*0.16;
//正确:调用函数applyDiscount,然后用函数的返回值初始化salePrice
double salePrice = applyDiscount(price, discount);
return 0;
}
ps:C++语言中,初始化和赋值时两个完全不同的操作,初始化不是赋值,初始化的含义是创建变量时赋予其一个初始值,而赋值的含义是把对象的当前值擦除,而已一个新值来替代。
3.列表初始化
C++语言定义了初始化的几种不同形式,这也是初始化问题复杂性的一个体现。例如,想要定义一个名为units_sold的int变量并初始化为0,以下的4条语句都可以做到这一点:
#include<iostream>
using namespace std;
int main(void)
{
int units_sold = 0;
//c++11新标准,用花括号初始化变量,在此之前这种初始化的形式仅在某些受限的场合下才能使用,
//这种初始化的形式被称为列表初始化,现在无论是初始化对象还是某些时候为对象赋新值,都可以使用这样一组由花括号括起来的初始值了。
int units_sold = {0};
int units_sold{0};
int units_sold(0);
return 0;
}
当用于内置类型的变量时,这种初始化形式有一个重要的特点:如果我们使用列表初始化且初始值存在丢失信息的风险,则编译将报错:
#include<iostream>
using namespace std;
int main(void)
{
long double ld = 3.1415926536;
int a{ld},b = {ld}; //错误:转换未执行,因为存在丢失信息的风险
int c(ld),d = ld; //正确:转换执行,且确实丢失了部分值,输出c=3,d=3
return 0;
}
使用long double的值初始化int变量时可能存在丢失数据,所以编译器拒绝了a和b的初始化请求。
4.默认初始化
如果定义变量时没有指定初值,则变量被默认初始化,此时变量被赋予了“默认值”。默认值到底是什么由变量类型决定,同时定义变量的位置也会对此有影响。
绝大数类都支持无须显式初始化而定义对象,这样的类提供了一个合适的默认值。例如:
#include<iostream>
#include<string>
using namespace std;
int main(void)
{
string empty; //empty非显式地初始化为一个空字符串
Sales_item item; //被默认初始化的Sales_item对象
return 0;
}
一些类要求每个对象都显式初始化,此时如果创建了一个该类的对象而未对其明确的初始化操作,将引发错误。
ps:定义于函数体内的内置类型的对象如果没有初始化,则其值未定义。类的对象如果没有显示地初始化,则其值由类确定。
5.变量声明和定义的关系
为了允许把程序拆分成多个逻辑部分来编写,C++语言支持分离式编译机制,该机制允许将程序分割为若干个文件,每个文件可变独立编译。
为了支持分离式编译,C++语言将声明和定义区分开来。声明使得名字为程序所知,一个文件如果想使用别处定义的名字而必须包含对那个名字的声明。而定义负责创建与名字关联的实体。
变量声明规定了变量的类型和名字,这一点上定义与之相同。但是除此之外,定义还申请存储空间,也可能会为变量赋一个初始值。
如果想声明一个变量而非定义它,就在变量明前添加关键字extern,而且不要显示地初始化变量:
extern int i; //声明i而非定义i
int j; //声明并定义j
任何包含了显示初始化的声明即成为定义。我们能给由extern关键字标记的变量赋一个初始值,但是这么做也就抵消了extern的作用。extern语句如果包含初始值就不再是声明了,而变成定义了:
extern double pi =3.1416 //定义了pi,而非声明pi非定义pi
在函数体内部,如果试图初始化一个由extern关键字标记的变量,将引发错误:
#include<iostream>
using namespace std;
extern int a;
int main(void)
{
extern int b = 1; //在函数体内定义了extern关键字标记的变量b,将引发错误
a = 0; //在函数体内定义了extern关键字标记的变量a,将引发错误
return 0;
}
ps:变量能且只能被定义一次,但是可以被多次声明。
如果要在多个文件中使用同一个变量,就必须将声明和定义分离。此时,变量的定义必须出现在且只能出现在一个文件中,而其他用到该变量的文件必须对其进行声明,却绝对不能重复定义。
总结
1.什么是变量?->变量提供了一个具名的,可供操作的存储空间。
2.怎么定义变量?->基本形式是:类型说明符+一个或多个变量名组成的列表,其中列表名以逗号分隔,最后以分号结束。
3.什么是初始值?->创建对象进行初始化并赋予的一个值。
4.什么是默认初始化?->定义变量没有指定初值,变量会被默认初始化赋予“默认值”,“默认值”有变量类型决定。
5.声明与定义的区别?->声明让变量名为程序所知,而定义则负责创建与变量名关联的实体。
6.声明与定义的注意事项:
1.如果需要声明变量名则在变量类型前添加关键字extern。
2.不要给由extern关键字标记的变量赋,否则会抵消extern的作用,也就使声明变成了定义。
3.不能在函数体内,初始化一个由extern关键字标记的变量。