您的位置:首页 > 运维架构 > Linux

Unix/Linux C++应用开发-C++基础概念"变量存储"

2013-09-11 20:55 477 查看
计算机程序处理与内存处理是紧密相连的。计算机程序中的不同的变量定义所使用的内存区域通常根据划分是不同的。例如,计算机程序代码存储于内存代码区。全局变量以及静态变量存储于全局与静态内存区域。常见常量数据存储于内存中专门为常量开辟的区域。函数调用以及函数参数以及内部局部变量定义等存储于内存栈空间。动态获取分配内存通常来源于堆内存空间。本小节主要讲述C++语言中三种常见类型变量以及动态存储基本概念和应用情况。

7.8.1  变量定义与赋值

高级计算机程序语言中将数据存放空间抽象出变量这个代称。应用程序中变量名是系统内存空间的某个名称代表。所以C++语言中规约了很多的变量类型,其实就是约定每种标准的数据类型所代表的存储空间的信息。例如,整型变量类型为int,定义其一个int类型的变量成为data,此时data仅仅是内存中4个字节空间的一个名称(大部分32位平台的整型大小)。

程序中操作这些变量,实际上就是操作内存空间来存取相应的数据。当然程序中操作变量的内存空间是从内存空间分配任意块中的首地址开始,通过位移方式计算出数据类型约定的大小空间作为一个变量的存储空间。C++语言中,变量的使用分为两个部分,即声明定义以及赋值。下面通过一些简单的变量声明定义和赋值实例来讲述应用程序中变量的基本操作情况。

extern int  a;

int     testData;

testData = 0;

int     testData1= 0;

char c=’c’;

int     *pData= &testData;

通常C++语言中变量声明和定义的区别就是是否在建立变量的同时开辟相应的内存存储空间。变量声明的概念通常是指变量仅仅取名并不建立相应的存储空间。如上述变量实例中第一个关键字为extern的代码示例,该段代码表示整型变量a在外部使用的代码片段处定义建立相应的存储空间。此时的变量a仅仅是个声明,并不建立相应整型大小的内存空间。

代码实例第二个定义了整型变量testData,该变量表示整型大小的内存空间。随后一行代码在该变量建立之后初始化相应的0值。代码实例第三在定义整型变量testData1的同时进行了初始化工作,将该变量初始化为值0。同样第四个实例同第三个,仅仅变量类型不同。

最后一个代码片段定义了一个整型指针,该指针定义的同时指向了变量testData的内存空间,因此该指针指向的内存空间存放的值为testData相应的变量值。

从上述实例分析来看,C++代码的变量分为声明和定义两个部分。声明一个变量并不建立相应的内存空间,仅仅是定义一个变量的名称,如上述采用关键字extern。定义一个变量在建立相应的变量名称之外还会建立相应内存空间,此时内存空间中存放的值并不确定。当然在C++语言中全局变量通常会进行默认初始化0工作。一般开发者定义变量使用,尤其是局部变量时最好养成初始化的好习惯,尤其是指针使用的情况下。

7.8.2  全局变量

全局变量定义在代码文件的任何函数之外,编译器依次来区别其它不同类型变量定义。全局变量在整个文件域中都有效,即全局变量可以被文件中任意函数代码处理。除此之外,在多文件C++代码中,全局变量可以跨文件使用。由于多文件中全局变量随时有可能被修改的危险,另外在多线程等并发程序中涉及数据共享同步问题。因此,在C++面向对象中类多个对象需要共享数据时,除非特殊情况下一般都是用静态成员变量代替全局变量,完全是出于数据安全性考虑的。下面通过一个完整的全局变量实例,了解全局变量在C++软件程序中的基本应用情况。

1.准备实例

打开UE工具,创建新的空文件并且另存为chapter0709.cpp。该代码文件随后会同makefile文件一起通过FTP工具传输至Linux服务器端,客户端通过scrt工具访问操作。程序代码文件编辑如下所示。

/**

* 实例chapter0709

* 源文件chapter0709.cpp

* 全局变量应用实例

*/

#include <iostream>

using namespace std;

 

int g_count;   //global variable

 

void doSomeThing1();

void doSomeThing2();

 

int main()

{

         g_count=1;

       cout<<"g_count startvalues:"<<g_count<<endl;

       doSomeThing1();

       doSomeThing1();

       cout<<"doSomeThing1after:"<<endl;

       cout<<"g_countvalues:"<<g_count<<endl;

       doSomeThing2();

       doSomeThing2();

       cout<<"doSomeThing2after:"<<endl;

       cout<<"g_countvalues:"<<g_count<<endl;

       return 0;

}

 

void doSomeThing1()

{

  ++g_count;

}

 

void doSomeThing2()

{

  --g_count;

}

本实例程序主要用于演示全局变量在C++应用程序中基本使用情况。程序主要由于两个操作全局变量作运算的函数以及主函数组成。函数方法内部处理非常简单,简单的做了前缀++和前缀--的运算。主函数中,首先初始化全局变量g_count值为1,打印输出其初始化后的值;其次调用两次doSomeThing1方法,方法内部做了++操作,随后输出doSomeThing1方法操作全局变量之后的值;最后调用函数doSomeThing2两次,打印输出运算--之后的全局变量值。

2.编辑makefile

Linux平台下需要编译源文件为chapter0709.cpp,相关makefile工程文件编译命令编辑如下所示。

OBJECTS=chapter0709.o

CC=g++

 

chapter0709: $(OBJECTS)

         $(CC)$(OBJECTS) -g -o chapter0709

clean:

         rm -fchapter0709 core $(OBJECTS)

submit:

         cp -f-r chapter0709 ../bin

上述makefile文件套用前面的模板格式,主要替换了代码文件、程序编译中间文件、可执行程序等。可以在编译命令部分加入-g选项,用于程序编译同时加入了可调式信息。

3.编译运行程序

当前shell下执行make命令,生成可执行程序文件,随后通过make submit命令提交程序文件至本实例bin目录,通过cd命令定位至实例bin目录,执行该程序文件运行结果如下所示。

[developer@localhost src]$ make

g++    -c -ochapter0709.o chapter0709.cpp

g++ chapter0709.o -o chapter0709

[developer @localhost src]$ ./chapter0709

g_count start values:1

doSomeThing1 after:

g_count values:3

doSomeThing2 after:

g_count values:1

全局变量的使用一般在程序开发中是谨慎的,因为对于一个程序模块其内部各个方法共同拥有的对某个变量的操作控制权并不是一件好事。大部分需要使用全局共享的情况建议尽可能的采用静态变量的方式。但是对于大量的全局常量,由于没有被局部代码修改的危险,因此通常会采用专有的头文件定义,以全局方式供各个模块使用。目的是统一程序中某些存在共性的常量值,如错误代码定义、程序状态类型值等等。

7.8.3  局部变量

局部变量主要定义于代码块内部,其作用范围往往也是在代码块中,局部变量的生命周期开始于代码块定义之处,结束于代码块执行结束之处。日常开发中,代码中的局部变量应用非常广泛。不管是在代码中函数内部,还是在面向对象的封装类型中,局部变量是基本的数据处理单位。下面同样通过一个简单的完整实例,演示局部变量在C++程序中的应用。

1.准备实例

打开UE工具,创建新的空文件并且另存为chapter0710.cpp。该代码文件随后会同makefile文件一起通过FTP工具传输至Linux服务器端,客户端通过scrt工具访问操作。程序代码文件编辑如下所示。

/**

* 实例chapter0710

* 源文件chapter0710.cpp

* 局部变量应用实例

*/

#include <iostream>

using namespace std;

 

void doSomething();

 

int main()

{

         intcount = 1; //a local variable

         doSomething();

         count= count+1;

         cout<<"doSomethingafter count:"<<count<<endl;

         return0;

}

 

void doSomething()

{

         intcount=0;  //a local variable

         for(inti = 0;i <= 5;i++)

         {

                   count+= 1;

         }       

         cout<<"localvariable count:"<<count<<endl;

}

本实例程序主要演示了局部变量在程序中使用情况。本实例中共定义两处名称相同的局部变量,由于局部变量作用域仅仅在代码块内部,因此不相干的代码块之间变量名相同并不会产生任何影响。实例共两个部分组成,函数doSomething()和主函数。

其中函数doSomething()中定义局部变量count,定义同时初始化为0。随后通过for循环语句,限定循环6次,循环体中作了count+1的运算。最后打印输出该变量的计算值。主函数中,同样定义局部变量count,同时初始化为1。为了演示局部变量在代码块中作用域之间互不相干,此处调用doSomething()方法,同时主函数中作count+1运算,最后打印输出验证结果。

2.编辑makefile

Linux平台下需要编译源文件为chapter0710.cpp,相关makefile工程文件编译命令编辑如下所示。

OBJECTS=chapter0710.o

CC=g++

 

chapter0710: $(OBJECTS)

         $(CC)$(OBJECTS) -g -o chapter0710

clean:

         rm -fchapter0710 core $(OBJECTS)

submit:

         cp -f-r chapter0710 ../bin

上述makefile文件套用前面的模板格式,主要替换了代码文件、程序编译中间文件、可执行程序等。在编译命令部分-g选项的加入,表明程序编译同时加入了可调式信息。

3.编译运行程序

当前shell下执行make命令,生成可执行程序文件,随后通过make submit命令提交程序文件至本实例bin目录,通过cd命令定位至实例bin目录,执行该程序文件运行结果如下所示。

[developer@localhost src]$ make

g++    -c -ochapter0710.o chapter0710.cpp

g++ chapter0710.o -g -o chapter0710

[developer @localhost src]$ ./chapter0710

local variable count:6

doSomething after count:2

通过上述实例演示,初学者需要明白局部变量作用域以及基本的使用情况。日常代码开发中,清楚的了解局部变量的作用域以及相应的生命周期非常重要。基本上无论是代码块还是对象封装数据中,这些局部变量的使用决定了数据在程序中的走向和终止情况。上述实例也表明局部函数代码块中定义的变量在函数调用的外部已经消亡,因此根据变量域定义外部同样命名的变量并不受影响。

7.8.4  静态变量

与前面变量所不同,静态变量生命周期以及存储空间的分配上稍有区别。前面无论介绍的全局变量还是局部变量,相对静态变量其区别重点是不同的。全局变量与相应的全局静态变量不同的是其变量值的可见性上。全局变量是可以跨文本共享操作的,而全局静态变量则仅限于本代码文本上可见并且共享。

局部变量和静态变量可以从生命周期以及其值的有效性上区别,局部变量随着代码块或者函数的调用执行而生,结束执行而亡。同时局部变量的值也会随着每次的执行而变化,静态局部变量则不同,虽然同为局部变量,但是当代码块或者函数调用结束时并不会被清除,其值也保留下来作为下次进入该域时该变量的初值。下面将会通过一个完整的实例演示静态变量的基本操作应用情况。

1.准备实例

打开UE工具,创建新的空文件并且另存为chapter0711.cpp。该代码文件随后会同makefile文件一起通过FTP工具传输至Linux服务器端,客户端通过scrt工具访问操作。程序代码文件编辑如下所示。

/**

* 实例chapter0711

* 源文件chapter0711.cpp

* 静态变量应用实例

*/

#include <iostream>

using namespace std;

 

static int g_count = 0;

 

void testCount1();

void testCount2();

 

int main()

{

         g_count= 4;

         testCount1();

         cout<<"g_countvalue:"<<g_count<<endl;

         testCount1();

         cout<<"g_countvalue:"<<g_count<<endl;

         testCount2();

         testCount2();

         testCount2();

         return0;

}

 

void testCount1()

{

         g_count= g_count*4;

}

 

void testCount2()

{

         staticint count1;

         intcount2 = 0;

         count1= (count1*2) + 1;

         cout<<"count1value:"<<count1<<endl;

         count2= (count2*2) + 1;

         cout<<"count2value:"<<count2<<endl;

}

本实例主要演示了静态全局变量、静态局部变量以及局部变量在C++程序中使用情况,体现局部变量与静态局部变量区别。程序由testCount1和testCount2两个函数以及主函数组成,具体程序讲解见程序剖析。

2.编辑makefile

Linux平台下需要编译源文件为chapter0711.cpp,相关makefile工程文件编译命令编辑如下所示。

OBJECTS=chapter0711.o

CC=g++

 

chapter0711: $(OBJECTS)

         $(CC)$(OBJECTS) -g -o chapter0711

clean:

         rm -fchapter0711 core $(OBJECTS)

submit:

         cp -f-r chapter0711 ../bin

上述makefile文件套用了上个实例模板。之所以其中采用变量定义替换的方式,目的就是为了方便编译程序的替换。从makefile工程文件中可以看出,布局是相同的。不同的地方仅仅是代码的文件名、生成可执行程序的名称等,大大方便了每次都要重新编写一遍编译命令的编辑方式。

3.编译运行程序

当前shell下执行make命令,生成可执行程序文件,随后通过make submit命令提交程序文件至本实例bin目录,通过cd命令定位至实例bin目录,执行该程序文件运行结果如下所示。

[developer@localhost src]$ make

g++    -c -ochapter0711.o chapter0711.cpp

g++ chapter0711.o -g -o chapter0711

[developer @localhost src]$ make submit

cp -f -r chapter0711../bin

[developer @localhost src]$ cd ../bin

[developer @localhost bin]$ ./chapter0711

g_count value:16

g_count value:64

count1 value:1

count2 value:1

count1 value:3

count2 value:1

count1 value:7

count2 value:1

4.程序剖析

上述实例程序两个函数方法主要实现一些变量计算工作。函数testCount1()主要用于操作全局静态变量g_count的计算工作,而函数testCount2()主要用于操作静态局部变量count1和局部变量count2的计算工作。

函数testCount1()中针对全局静态变量g_count进行了乘4并且通过赋值的方式更新该变量的处理,函数testCount2()中首先定义静态局部变量count1和局部变量count2,由于C++中局部变量定义时不初始化,通常其值为一个未知的数值。因此必须在每次定义局部变量时初始化。此时count2变量的初始值为0。

函数testCount2()中,随后针对静态局部变量count1进行乘2加1计算并且打印输出其计算结果。之后针对局部变量同样进行了乘2加1运算,打印输出其计算结果。主函数的执行流程中体现了整个程序实例的含义。

首先给全局静态变量g_count赋值,由于全局变量通常在C++语言中都会在定义时默认初始化值。因此主函数中g_count=4仅仅能看作是赋值操作。调用testCount1()函数,内部针对全局静态变量进行乘4的计算,然后打印输出该变量结果,两次调用从打印输出结果来看静态变量每次调用处理的值都是上次计算结果保留下来的值。

其次,主函数中调用了三次testCount2()函数操作。该函数内部包含两个部分,一个是静态局部变量的计算操作,另一个是局部变量的计算操作。从打印输出结果来看,静态局部变量尽管是局部变量的情况出现的,但是其值以及变量本身并没有随着函数调用结束而终结。证明了静态变量值的继承性以及变量的生命周期的区别。

7.8.5  动态存储

前面变量小节中已经明白这样一个概念,C++语言中针对使用的内存空间给出了变量的定义,同时规约了各种数据类型在内存空间中所占的大小以及位置。这一切在程序编译的时候编译器统统帮助开发者完成了,即在使用某种数据类型如int整型变量,在编译阶段系统就已经为程序分配了一个固定的内存空间给其使用。

但是应用程序中除了静态的分配使用存储空间以外,还有程序运行过程中的动态分配使用要求。C++语言针对这种需求同样提供了动态分配内存的方法。因为动态分配存储是需要开发者自行管理并且释放的,因此在语言层面提供了new和delete一对相互申请和释放功能的关键字。

new关键字表示从内存动态申请所需大小的存储空间,delete关键字用于在动态申请的内存空间使用完毕的基础上作相应的释放操作。通常new和delete都必须成对的出现,否则在程序运行阶段容易出现内存泄漏的问题。下面将会通过一个完整的实例演示C++动态存储基本使用情况。

1.准备实例

打开UE工具,创建新的空文件并且另存为chapter0712.cpp。该代码文件随后会同makefile文件一起通过FTP工具传输至Linux服务器端,客户端通过scrt工具访问操作。程序代码文件编辑如下所示

/**

* 实例chapter0712

* 源文件chapter0712.cpp

* 动态内存申请释放实例

*/

#include <iostream>

using namespace std;

#define LENGTH 1024

 

char *applyMemory(unsigned long size)

{

           char *pPointer = new char[size + 1];

           return pPointer;

}

 

int main()

{

           char str[LENGTH] = "Hello C++!";

           char *p = NULL;

           p = applyMemory(LENGTH);

           strcpy(p,str);

           cout<<"p pointer'svalue:"<<p<<endl;

           if(p != NULL)

           {

                cout<<"deletememory!"<<endl;

             delete []p;

             p = NULL;

           }

           return 0;

}

本实例程序主要演示了动态申请和释放字符类型内存操作使用情况。程序主要包含动态申请内存函数与主函数两个部分,程序具体讲解见程序剖析部分。

2.编辑makefile

Linux平台下需要编译源文件为chapter0712.cpp,相关makefile工程文件编译命令编辑如下所示。

OBJECTS=chapter0712.o

CC=g++

 

chapter0712: $(OBJECTS)

         $(CC)$(OBJECTS) -g -o chapter0712

clean:

         rm -fchapter0712 core $(OBJECTS)

submit:

         cp -f-r chapter0712 ../bin

上述makefile文件套用前面的模板格式,主要替换了代码文件、程序编译中间文件、可执行程序等。在编译命令部分-g选项的加入,表明程序编译同时加入了可调式信息。

3.编译运行程序

当前shell下执行make命令,生成可执行程序文件,随后通过make submit命令提交程序文件至本实例bin目录,通过cd命令定位至bin目录,执行该程序文件运行结果如下所示。

[developer@localhost src]$ make

g++    -c -ochapter0712.o chapter0712.cpp

g++ chapter0712.o -g -o chapter0712

[developer @localhost src]$ make submit

cp -f -r chapter0712../bin

[developer @localhost src]$ cd ../bin

[developer @localhost bin]$ ./chapter0712

p pointer's value:Hello C++!

delete memory!

4.程序剖析

本实例主要包含动态申请内存和主函数两个部分。动态申请内存函数applyMemory()传入参数为无符号长整型数据,该参数size用于函数内部申请内存的长度。函数applyMemory()返回值为char*指针,表明函数处理最终返回指向申请到的内存空间的首地址。

主函数中首先定义字符数组str,该数组长度为宏定义LENGTH为1024。数组str中存放字符串"HelloC++!",随后定义char型指针p并且初始化为NULL。调用动态申请内存函数applyMemory,传入需要的申请内存长度,返回值赋值给指针p。此时主函数中的指针p指向了动态申请的新内存首地址。

通过strcpy()拷贝方法,将str指向内存空间拷贝给指针p。此时p指向的地址中存放了字符串"Hello
C++!"。动态申请的空间当使用完毕之后,先判断是否指向为空,如果为空则将其申请的动态内存通过delete关键字释放,同时将p指针指向置为空。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: