2.2变量

变量

变量提供一个具有具体名字的、可供程序操作的存储空间(相当于汇编语言中的寄存器)。

1.变量和对象

变量和对象的区别:

  • 变量:每个变量都有其数据类型,数据类型决定所占内存的大小和能参与的运算。
  • 对象:对象是指一块能存储数据并具有某种类型的存储空间。

对C++来说,“变量”和“对象”一般可以互换使用。一般来说,对于内置类型创建的叫变量,内置类型创建的叫对象。其实都是一个东西。

2.变量的定义

变量定义的基本形式是:类型说明符+一个或多个变量名组成的列表(其中变量名以逗号分隔,最后以分号结束)

列表中的每个变量名的类型都由类型说明符指定,定义时还可以为一个或多个变量赋值。

如:

int sum=0,value,unit_sold=0;  //定义内置类型变量,其中sum和unit_sold初始化为0,value默认初始化
Sales_item item;              //定义自定义类型item变量,采用默认初始化
std::string book("0-201-78x");//定义库类型对象string,采用直接初始化方式

3.变量的初始化形式

①声明和初始化和赋值的关系:

  • 声明:指定一个变量的名字,仅仅是让编译器知道有这个名字,而没有实际分配空间
  • 初始化:给一个声明后尚未初始化后的变量一个有意义的初始值。
  • 赋值:销毁一个变量原来的值,并赋予一个新值。

②变量的初始化形式具有4种形式:

  1. 直接初始化调用与实参匹配的有参构造函数,如:

    string s1("hiya");   //直接初始化,s1初始化为"hiya"
    string s2(10,'c');   //直接初始化的第二种方式,将s2初始化成10个'c'
    
  2. 拷贝初始化:使用=初始化一个变量,执行的是拷贝初始化。 如:

    string s1="huya";
    int units_sold=0;
    

    初始值只有一个时,使用直接初始化或拷贝初始化都可以,但如果初始值有多个,则一般只能使用直接初始化方式,使用拷贝初始化的话会创建一个临时对象用于拷贝:

     //只有一个初始值"abc",拷贝初始化等同于直接初始化
    string s1 = "abc";  
    string s2("abc");    
    //有多个初始值'c',一般用值初始化,使用拷贝初始化会创建临时变量
    string s3(10,'c');        //直接初始化
    string s4=string(10,'c'); //必须用这种形式来拷贝初始化
    
  3. 列表初始化: 列表初始化在C++11中可以用于以下几种情况

    (1)用于数组初始化,如:

    int arr[]={1,2,3};
    int arr2[]{1,2,3,4};
    

    (2)用于STL容器初始化,如vector,string等,如:

    vector<int> v1{1,2,3};
    string s{"abc"};
    

    (3)用于new操作等圆括号进行初始化的地方,如:

    int *a = new int {3};
    double b = double{12.12};
    int *arr =new int[] {1,2,3};
    

    (4)用于聚合体的初始化(所有成员都是public的;没有定义任何构造函数;没有类内初始值;没有基类也没有virtual函数),要求**初始值顺序必须和声明顺序一致。**如:

    struct Data{
      int val;
        string s;
    };
    Data v = {0, "OK"};     //正确
    Data v2 = {"OK", 0};    //错误:初始值顺序必须和声明顺序一致
    
  4. 默认初始化:

    • 对于内置类型:如果变量定义在所有函数体外,则初始化为0;如果定义在函数体内,则不被初始化没有定义(使用未定义的变量将会产生不确定的后果,编译会报错)

    • 对于自定义类型:一般来说都可以无需初始化定义(会调用默认构造函数);如果一些类定义时必须要求促使话则会发生错误。

  5. 值初始化:

    值初始化效果

    • 内置类型零初始化对象
    • 数组则值初始化数组的每个元素
    • 如果类类型有用户定义的默认构造函数,则执行用户定义的默认构造函数;如果有合成的默认构造函数,则先进行零初始化后再执行合成的默认构造函数。

    值初始化用于以下几种情况

    (1) 以空的括号或花括号对组成的初始化器创建无名临时对象时,如:

    int v1 = int{}; //v1=0
    double f1 = double(); //f1=0.0
    

    (2) 用new表达式以空括号或花括号创建堆区动态对象时,如:

    int *p1 = new int(); //p1指向的内存值为0
    int *p2 = new int[10](); //p2指向的数组每个值都为0
    int *p3 = new int[]{1011}; //p3指向数组有2个元素,分别为10,11
    

    (3)以由空花括号创建自定义对象时, 如:

    //有合成的默认构造函数
    struct A1{
    int v=1;
    string s;
    };
    //无默认构造函数
    stuct A2{
    int v;
    string s;
    A2(int v){}
    };
    //有自己定义的默认构造函数
    struct A3{
    int v;
    string s;
    A3(){}
    };
    A1 a1{};    //合成默认构造函数零初始化后再初始化,v=0,s为空
    A2 a2{};    //错误:类无默认构造函数不能初始化
    A3 a3{};    //自己定义的构造函数来进行默认初始化,v随机值,s为空
    

4.变量声明与定义的关系

为了允许把程序拆分成多个逻辑部分来编写,C++语言支持分离式编译机制,该机制允许将程序分割为若干个文件,每个文件可被独立编译。

为了支持分离式编译,C++将声明和定义区分开来。声明使得名字为程序所知,定义负责创建与名字关联的实体。

如果想要声明一个变量,就要在变量名前加上extern,而不要显示地初始化对象

如:

extern int i;     //声明i而非定义i
int j;            //声明并定义j
extern int k=1;   //声明并定义k

**变量能且只能被定义一次,但是可以被声明多次。**如果在多个文件中使用同一个变量,就必须将声明和定义分离,此时,变量的定义必须出现在且只能出现在一个文件中,而其他用到该变量的文件必须对其进行声明,绝对不能对其进行重复定义。

5.名字的作用域

5.1作用域定义

作用域(也叫块):一般用花括号分隔,名字的有效区域始于名字的声明语句,结束于声明语句所在作用域的末尾。

位于所有花括号之外的作用域称为全局作用域,全局作用域的名字在整个程序的范围内都可以使用。位于花括号之内的作用域称为局部作用域(块作用域)块作用域内的变量只能在块内使用,变量出了局部作用域便会被销毁。

如:

#include<iostream>
using namespace std;
int main(){
    int sum=0;
    for(int i=0;i<10;++i){   //变量i只存在于for循环内的块区域内
        su+=i;
    }
    cout<<i<<endl;           //i不在for循环块内,没有定义i,所以无法访问
}

5.2嵌套的作用域

作用域能彼此包含,被包含(嵌套)的作用域被称为内层作用域,包含着别的作用域的作用域被称为外层作用域

作用域一旦声明了某个名字,它所嵌套着的所有内层作用域都能使访问该名字。同时允许在内层作用域中重新定义外层作用域已有的名字,这样会屏蔽外层作用域已有名字的定义。

如:

#include<iostream>
using namespace std;
int main(){
    double i(3.1415);        //main函数的花括号是外层作用域,定义了double的i
    int sum=0;
    for(int i=0;i<2;++i){    //for循环块内是内层作用域,重新定义了i,屏蔽了外层i的名字
        sum+=i;
        cout<<i<<' ';
    }
    cout<<i<<endl;           //内层作用域的i变量出了内层作用域被销毁,打印外层作用域变量i
}

结果为:0 1 3.1415

建议:

  1. 第一次使用变量时再定义它
  2. 如果函数有可能用到某全局变量,则不宜再定义一个同名的局部变量
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值