【C++探索之旅】第一部分第四课:内存,变量和引用



内容简介

1、第一部分第四课:内存,变量和引用

2、第一部分第五课预告:简易计算器


内存,变量和引用

上一课《【C++探索之旅】第一部分第三课:第一个C++程序》中,我们已经学习了如何创建,编译,运行我们的第一个C++程序。我们也解释了这个程序每一行的意义。

我们不但在IDE(Integrated Development Environment,集成开发环境。例如Visual Studio,Codeblocks,xCode等)中创建程序,也学习了如何在终端命令行中创建。

不过到目前为止,我们写的程序还非常简单,只能在屏幕上显示消息,还不能和用户进行交互。我们慢慢来弥补这一缺憾。

在此之前,我们首先来学习一个计算机科学的基本概念,就是:变量。

变量使用电脑的内存来存储信息,以便之后再次使用。大家应该用过计算器吧,我们平时不太使用的几个键:M+,M-,MR,MC,其实就是在使用变量和内存的概念(M是Memory的缩写,表示《内存》),这几个键的作用如下:

M+:把目前显示的值放在存储器中 (memory +)

M- :从存储器内容中减去当前显示值 (memory -)

MR:调用存储器内容 (memory recall)

MC:清除存储器内容 (memory clear)

以上这些按键,可以操作存储在计算器的存储器(内存)里的计算值。

我们将在电脑上学习类似的事情,毕竟我们的电脑兄说到底不过是一台大“计算器”,本质上就是做二进制(0和1)的运算,不然也不会叫“计算机”了对吧。



什么是变量

上面我们举了计算器的例子来更形象地说明,毕竟在信息技术的世界里,基本的原理是相通的。在我们的电脑里,也有一些电子元件,可以储存数值,并且能保存一段时间。当然,背后的科学原理是比较复杂的。

不过大家可以放心,我们没必要搞清楚这背后的一套复杂的原理,我们只需要学会怎么把数值存储到电脑的内存中就好了。至于复杂的部分就交由编译器和操作系统来处理了,是不是突然觉得生活很美好呢?

我们只需要知道变量其实就是电脑借给我们的一小段内存,里面储存了数值。我们可以想象电脑里面有一个大橱柜(比喻内存),如下图所示。这个大橱柜非比寻常,因为它拥有成千上万(甚至数十亿)个小抽屉,这些小抽屉就是内存中我们可以存放数值的地方。

电脑的内存的原理就有点像一个有着很多抽屉的大橱柜。

对于一个计算器来说,我么通常一次只能储存一个数值。但是我们的电脑可比普通的计算器厉害多了。不然也不会那么贵了,对吧?说的就是你,苹果电脑。

聪明如你应该料想到了:在C++程序中,我们可以同时储存很多变量。因此,就需要区分这些变量,以便之后调用时可以分得清谁是谁。因此,在C++程序中,每个变量拥有一个名字。这个名字就有点像上图中的抽屉外面贴的标签,使我们能够找到所要的抽屉。

我们的电脑还可以使我们储存不同的数值,比如我们想储存数字,字母,单词,句子,图片,声音,等等。这就涉及到变量的类型了。

你可以想象变量的类型就好比抽屉的不同样式,在生活中,我们放葡萄酒和书籍的抽屉是不一样的,不是吗?

变量名

对于人来说,名字很重要,名字起得好,有很多益处。名字起得不好,会很搞笑。

变量也有名字,而给C++中的变量起名字有如下规则:

  1. 只能包含字母,数字和下划线(_)
  2. 第一个字符必须是字母或下划线
  3. 不能和C++的关键字重复,比如不能是int,char,if,while等。

例如:

name,studentNum,year2015,_computerPrice 等都是规范的命名。

而:

+animal,@gmail,*1991,等都是通不过的命名。

除此之外,C++对于大小写敏感。也就是说,大写字母和小写字母在C++看来是不同的。有的编程语言不区分大小写。所以,在C++中,givenName,GIVENname,GiVenName是不同的变量名。

另外,希望大家养成良好的命名习惯,使自己的变量做到见名知意,这样程序就可以自注释了。比如,我们提倡这样的变量名:myName,computerPrice。而不推荐类似 name1,variable3,hehe2,之类不知所云的名字。

对于程序的编译器来说,这样并没有什么用,因为它才不管你名字起得是不是见名知意。但是,对于你自己和以后要阅读你的程序人来说,一个好的变量名会发挥很大的作用,不然过了一段时间再看自己的代码,可能都忘了这个变量是用来干嘛的。

小编自己有个变量命名习惯,此习惯不少程序员也遵守:

  1. 变量名由小写字母开头
  2. 如果变量名由几个单词组成,那么紧挨着写
  3. 除了第一个单词,其他单词的第一个字母大写

例如:

bestRestaurantName,secondBugReport,等等。

这样的命名法也称为《小驼峰式命名法(lower camel case)》。

变量类型

之前说了,变量除了有名字,还有类型。就好比“小明”这个名字,不知道是人呢还是一只宠物。

C++的变量类型如下图所示:

有点多是吗?初学时不用一下子都记住,我们慢慢来学习。一开始只要知道几种常用的变量类型就可以了。如下:


常用类型


可以存储的数值


bool


true(真)或false(假)


char


一个字符


int


整数


unsigned int


无符号整数(正整数或0)


double


带小数点的数(其实double是双精度浮点数)


string


字符串(0到多个字符)

一般,我们在IDE中输入以上这些变量类型时,IDE会用颜色来高亮显示。

这些类型可储存的数值有大小范围,也就是上下限。比如有的很大的整数,int类型就不能储存。这些上下限取决于你的电脑,操作系统和编译器。

当我们使用变量时,就需要考虑用哪种变量类型了。例如你要储存一个学校的学生数目,那么int和unsigned int会适合。要储存一个人的身高,那么用double会适合。要储存你自己的名字,那么string会适合。

那么bool这种变量类型是什么意思呢?

bool其实是boolean(布尔类型)的意思,它只能储存两种值:true(真)或false(假)。

我们可以用bool类型的变量来储存例如: 用户名是否正确,是不是程序员,有没有女朋友,之类。



变量声明

变量的英语是variable,是《可变的,变化不定的》,所以说,变量和女人的心有点像,不是吗?开个小玩笑。

因此,变量储存的数值是可以改变的。

好了,铺垫也够多了,该来正式请求电脑出借它的“抽屉”了(前面我们用抽屉比喻一块内存空间)。用术语来说,就是变量声明。

注意:我们暂时用《声明》这个词,其实要澄清一下:

==========================


变量而言,声明与定义的关系稍微复杂一些。在声明部分出现的变量有两种情况:一种是需要在内存中建立存储空间的(如int
a;);另一种是不需要建立存储空间的(如extern int a;  以后会讲到extern关键字)。前者称为定义型声明(defining
declaration),或简称为定义(definition)。后者称为引用型声明(referenceing declaration)。

广
义地说,声明包括定义,但并非所有的声明都是定义。对 int a; 而言,它是定义性声明,既可说是声明,又可说是定义。而对 extern int
a; 而言,它是声明而不是定义。一般为了叙述方便,把建立存储空间的声明称为定义,而把不需要建立存储空间的声明称为声明。

在这一课中所有用到《声明》的地方,其实用的是《定义型声明》。以后的课会讲解《引用型声明》。

==========================

我们需要向电脑提供变量的类型,名字和它储存的值。这里的值会成为变量的初始值。

为了做到这一点,我们只需按照以下格式:

类型  名字  (值);

以上的格式是C++中初始化一个变量的方式。

我们也可以用另一种从C语言继承过来的格式:

类型  名字  = 值;

这两种格式的效果是一样的。我们推荐使用第一种格式,以后的课程中会讲述为什么选第一种格式更好。

可不要忘了句末的分号(;),这个错误即使是有经验的程序员也会犯。当然这个错误也不难发现,只不过它会让你的编译器不安分而已。

我们就来声明(定义型声明)一个变量,这个变量叫做userAge,用于储存《用户年龄》:

#include <iostream>

using namespace std;

int main()
{
    int userAge(16);
    
    return 0;
}

上面程序的第6行发生了什么呢?

答:电脑得知我们要向它的内存借一个“抽屉”,这个抽屉有以下特性:

  1. 可以储存整数
  2. 抽屉外面贴了一个标签,名叫 userAge
  3. 抽屉里储存的值是16

因此,一旦程序运行完了第6行代码,你就成为电脑内存中那个抽屉的主人了,如下图:

因为之后我们会继续向电脑借很多“抽屉”,所以我们需要把图画得简单些。如下:


我们来解释一下上图的意思:

  1. 大大的蓝色矩形代表的是电脑的内存,目前,内存几乎是空的。
  2. ***的小正方形代表电脑出借给我们的内存的一块空间。也就是我们之前比喻的一个抽屉。它里面储存的值是16,而它的标签是userAge。

既然我们画了如此好(chou)看(lou)的图,那岂能只声明一个变量。一不做二不休:

#include <iostream>

using namespace std;

int main()
{    
    int userAge(16);
    int money(432);  //钱数    
    double pi(3.14159);    
    bool isHoliday(true); //是不是假期    
    char letter(‘a‘);  
     
    return 0;
}

上面的程序中,我们在userAge这个变量之外,又声明了好几个新的变量。

有两点需要注意:

  1. bool类型的变量只能储存true或false中的一个值,不是true(真),就是false(假),除此之外不能储存其他值。
  2. char变量的值需要用单引号括起来,不要写成 char letter(c); 而是 char letter(‘c‘);

插一句题外话:写程序时要勤写注释,哪怕看似比较简单的地方,因为以后别人看你的程序,或者你自己回看自己的程序,假如没有注释,那可能会增加不少难度。

对于上面这个程序,我们也可以画一个图,只要在之前的图上增加新的变量即可。

可以看到,我们多声明了几个变量,内存里面开始变得丰富多彩起来了。马上要圣诞了,人多一些总是热闹。

上面的程序,我们如果编译,运行,可以看到它什么也没有输出。那是当然的,因为我们只是声明了一些变量,还没使用它们呢。

我希望你没有太失望,虽然这个程序没有显示什么,但其实在背后电脑是进行了很多操作的。只不过这些操作对用户隐藏起来了,我们也不太感兴趣而已。不过我们还是总结一下上面的变量声明究竟做了什么:

  1. 你的程序向操作系统(简称OS,是Operating System的缩写。例如Windows,Mac OS X,Linux等都是常见的操作系统)借一些内存来使用
  2. 操作系统查看内存是否有空余的空间,如果有则分配几个“抽屉”(代表内存空间)给你的程序
  3. 你的程序逐一将那些值存放进对应的抽屉。例如在贴有userAge标签的抽屉里,存放进16;在贴有money标签的抽屉里存放进432;等等
  4. 运行到最后一行(return 0;)时,你的程序把所有抽屉清空,并且还给操作系统

字符串的情况

前面说了,字符串这种变量类型的情况有点特殊。为了使用字符串变量,我们首先需要在程序中多加一行:

#include <string>

表示引入string这个C++的标准库,这样我们才能使用其中的函数等。我们可以写个程序:

#include <iostream>
#include <string>

using namespace std;

int main()
{
    string userName("Steve Jobs");
    
    return 0;
}

可以看到,我们声明了一个字符串变量,它的名字是userName,里面存放的值是Steve Jobs(苹果的前CEO)。

可以看到,给string型变量赋值,用的是双引号",而之前给char型变量赋值时用的是单引号‘。其实呢,字符串(string)就是由一串字符(char)组成的。

偷懒的小技巧

在继续下面的内容之前,我们介绍一种“偷懒”的小技巧,很多程序员都会用:

如果你有多个同一类型的变量要声明,那么可以将它们放在同一行里,彼此用逗号隔开。如下:

int a(2), b(4), c(6); //我们声明了三个整型变量a, b, c,分别存放了2, 4, 6三个值
string userNameApple("Steve Jobs"), userNameMicrosoft("Bill Gates");  
//我们声明了两个字符串变量userNameApple和userNameMicrosoft,分别存放Steve 
Jobs(史蒂夫乔布斯)和Bill Gates(比尔盖茨)。

这样我们就不用每次都写一遍变量类型名了,上例中是int和string。



声明但不初始化

上面我们学习了如何声明一个变量(其实是定义型声明),其实声明一个变量时你的程序陆续做了两件事:

  1. 首先,程序向操作系统请求拨给一块内存空间,称为“变量分配”。
  2. 然后,在这块内存空间上存入初始值,称为“变量初始化”。

但是,有的时候我们在声明变量时还没有想好要赋什么值。所以,我们也可以声明变量,但不初始化。

怎么做呢?很简单,只需要写变量类型和变量名,就可以了。如下:

类型  名字;

是不是很简单呢?我们来看例子程序:

#include <iostream>
#include <string>

using namespace std;

int main()
{     
    string qqName;  // QQ用户名
    string qqNumber; // QQ号
    bool isVIP;     // 是不是QQ的VIP会员
    
    return 0;
}

注意:有一个常见的错误是:

在变量名之后加空的括号,例如 string qqNumber();

这是不正确的,不要加括号,只需要类型和名字。

我们也用图解来演示上面的程序:

可以看到,在声明变量后,变量中的值是一个任意值。

但是通常我们最好在声明时给变量赋初值,特别是指针的情况,以后我们会学习。而且有的变量类型还必须在声明时就初始化。



显示变量的值

在上一课中,我们已经学习了如何在屏幕上显示文本,希望你没有忘记大明湖畔的夏雨荷。

是的,这位"夏雨荷"就是 cout<<

cout有点类似C语言的printf函数,是C++里面负责标准输出的。不过又有不同,我们可以看到cout后面不是加括号,而是连接了<<这个特殊的符号。

暂时我们不深入,因为cout其实不是一个函数,cout是一个ostream类的对象(关于类和对象,之后的课程会讲解),它有一个成员运算符函数
operator<<(涉及到C++的运算符重载的技术,以后会讲)。(这一句指令暂时不需要理解,只要知道cout<<可以用来向屏幕输出内容即可)。

那么机智如你,应该猜到怎么显示变量的值了吧。

是的,就是把文本替换成变量名就行了。如下:

cout << userAge;

这么简单,你敢信?

是的,就是这么简单。

#include <iostream>

using namespace std;

int main()
{
    int userAge(16);
    cout << "你的年龄是 : ";
    cout << userAge;
    
    return 0;
}

运行以上程序,显示:

你的年龄是 : 16

当然了,我们也可以同时显示好几个变量的值,并且把一句话的内容都写在一行上。如下:

#include <iostream>
#include <string>

using namespace std;

int main()
{
    int userIQ(150);
    string userName("Albert Einstein");  // 阿尔伯特.爱因斯坦
    
    cout << "你名叫 " << userName<< ", 你的智商是 " << userIQ<< endl;
    
    return 0;
}

运行以上程序,显示:

你名叫 Albert Einstein, 你的智商是 150



引用

在结束这一课之前,我们还有一个很重要的知识点需要介绍。

这个知识点就是:引用

《引用》的英语是reference。

我们之前说过,变量可以被看成内存里的一个“抽屉”。这个抽屉外面可以贴标签,就是变量名。

实际生活中,我们可以在同一个抽屉外面贴上不止一个标签。那么,在C++中,我们也可以给同一个内存的“抽屉”上贴好多个标签。

因此,我们就多了一种访问变量的方式。就好像我们给变量取一个别名。但是别名听起来没有那么高大上,所以C++中称之为“引用”。听着是不是挺玄乎的,其实就是别名。

我们可以用下图来演示:

可以看到,在内存中的这个变量上,有两个标签。一个是userAge,声明此变量时起的变量名;另一个是myVariable,是它的别名,也就是引用。

比如,黄晓明,也可以叫小明,两个名字指代的都是那个人,都爱着Angelababy。

那么引用怎么声明呢?要用到一个特殊的符号:&

int userAge(16);  // 声明一个变量,名字是userAge

int& myVariable(userAge); // 声明一个引用变量,名叫myVariable,它是userAge变量的别名。

可以看到,userAge放在了myVariable后面的括号里,还记得变量如何初始化吗?就是在括号里填入初始值。因此,这里相当于把userAge“赋值”给了myVariable

说到底,userAge和myVariable指向的是同一个“抽屉”,同一个变量。它们的值都是16。

用术语说就是:myVariable引用了userAge。

引用变量的类型必须和它要引用的变量一样。而且,引用变量声明时必须赋初值。

我们来看一个例子程序:

#include <iostream>

using namespace std;

int main()
{    

    int userAge(16); // 一个变量,名字是userAge,包含一个整型数值16        
    int& myReference(userAge); // 变量userAge的一个引用    

    // 从现在开始,我们可以不加区分地使用userAge或myReference    
    // 因为它们实际上是一个内存中“抽屉”的两个标签,指向的是相同内容    

    cout << "你已经 " << userAge << "  岁了. (通过 变量名)" << endl;    
    // 惯常的方式    
    
    cout << "你已经 " << myReference << " 岁了. (通过 引用)" << endl;    
    // 用引用的方式来访问变量值        

    return 0;
}

运行以上程序,显示:

你已经 16 岁了. (通过 变量名)

你已经 16 岁了. (通过 引用)

那么,引用到底有什么用呢?

好问题。在上面的例子中,仿佛看不出引用有多大用处。

也许暂时你觉得引用比较抽象,也貌似没什么用。但是要知道,引用是C++中很重要的一块知识点,而且以后我们会“大宝啊,天天见”,会经常使用到“引用”的。而且还会区分什么时候用引用,什么时候用指针。

因此,先对引用的概念有个了解,对我们之后处理更复杂的用例是大有裨益的。



总结

  1. 变量是存储在内存里的一段信息
  2. 根据存储的信息的不同,变量有不同类型:int,char,bool,double,等
  3. 变量在使用前需要先声明,例如:int number(28); // 此处是定义型声明
  4. 可以用cout来显示变量的值
  5. 引用其实是变量的别名,有点像标签,使我们可以用另一个名字来调用变量,例如:int& numberReference(number);

第一部分第五课预告

今天的课就到这里,一起加油吧!

下一课我们学习:简易计算器

时间: 2024-11-08 18:57:59

【C++探索之旅】第一部分第四课:内存,变量和引用的相关文章

【C语言探索之旅】 第一部分第四课第一章:变量的世界之内存那档事

内容简介 1.课程大纲 2.第一部分第四课第一章:变量的世界之内存那档事 3.第一部分第四课第二章预告:变量的世界之声明变量 课程大纲 我们的课程分为四大部分,每一个部分结束后都会有练习题,并会公布答案.还会带大家用C语言编写三个游戏. C语言编程基础知识 什么是编程? 工欲善其事,必先利其器 你的第一个程序 变量的世界 运算符 条件表达式 循环语句 实战:第一个C语言小游戏 函数 练习题 习作:完善第一个C语言小游戏 C语言高级技术 模块化编程 进击的指针,C语言王牌 数组 字符串 预处理 创

【C语言探索之旅】 第一部分第四课第二章:变量的世界之变量声明

内容简介 1.课程大纲 2.第一部分第四课第二章:变量的世界之变量声明 3.第一部分第四课第三章预告:变量的世界之显示变量内容 课程大纲 我们的课程分为四大部分,每一个部分结束后都会有练习题,并会公布答案.还会带大家用C语言编写三个游戏. C语言编程基础知识 什么是编程? 工欲善其事,必先利其器 你的第一个程序 变量的世界 运算符 条件表达式 循环语句 实战:第一个C语言小游戏 函数 练习题 习作:完善第一个C语言小游戏 C语言高级技术 模块化编程 进击的指针,C语言王牌 数组 字符串 预处理

C语言探索之旅】 第一部分第四课第三章:变量的世界之显示变量内容

内容简介 1.课程大纲 2.第一部分第四课第三章:变量的世界之显示变量内容 3.第一部分第五课预告:基本运算 课程大纲 我们的课程分为四大部分,每一个部分结束后都会有练习题,并会公布答案.还会带大家用C语言编写三个游戏. C语言编程基础知识 什么是编程? 工欲善其事,必先利其器 你的第一个程序 变量的世界 基本运算 条件表达式 循环语句 实战:第一个C语言小游戏 函数 练习题 习作:完善第一个C语言小游戏 C语言高级技术 模块化编程 进击的指针,C语言王牌 数组 字符串 预处理 创建你自己的变量

【Linux探索之旅】第一部分第四课:磁盘分区,并完成Ubuntu安装

内容简介 1.第一部分第四课:磁盘分区,并完成Ubuntu安装 2.第一部分第五课预告:Unity桌面,人生若只如初见 磁盘分区 上一课我们正式开始安装Ubuntu了,但是到了分区的那一步,小编却戛然而止.这是什么情况呢? 请读者们千万不要扁我:如果真的要扁,那就请"海扁",让我一次挨(爱)个够(想到了庾澄庆的<让我一次爱个够>),体会一下苏武的感觉. 是这样的:磁盘分区是个很重要且比较难的知识点. 所以我们单独用这一课来讲磁盘分区的概念,磁盘的组成,文件系统,等. 磁盘分

Linux探索之旅 | 第五部分第二课:一入Shell深似海,酷炫外壳惹人爱

-- 简书作者 谢恩铭 转载请注明出处 内容简介 前言 Shell是什么? 我们的第一个Shell脚本 运行Shell脚本 总结 第五部分第三课预告:变量在手,Shell不愁 1. 前言 上一课是 Linux探索之旅 | 第五部分第一课:Vim岂是池中物,宝剑锋从磨砺出 . 现在,我们已经学习了 Vim 这样强大的文本编辑器.相信我,Vim 对我们之后的课程会非常有用. 这一课我们可以进入第五部分的重心了:Shell 编程. 什么是Shell呢? 首先,shell 是英语"壳,外壳"的

【C语言探索之旅】 第二部分第二课:进击的指针,C语言的王牌!

内容简介 1.课程大纲 2.第二部分第二课: 进击的指针,C语言的王牌 3.第二部分第三课预告: 数组 课程大纲 我们的课程分为四大部分,每一个部分结束后都会有练习题,并会公布答案.还会带大家用C语言编写三个游戏. C语言编程基础知识 什么是编程? 工欲善其事,必先利其器 你的第一个程序 变量的世界 运算那点事 条件表达式 循环语句 实战:第一个C语言小游戏 函数 练习题 习作:完善第一个C语言小游戏 C语言高级技术 模块化编程 进击的指针,C语言王牌 数组 字符串 预处理 创建你自己的变量类型

【Linux探索之旅】第二部分第二课:命令行,世界尽在掌握

内容简介 1.第二部分第二课:命令行,世界尽在掌握 2.第二部分第三课预告:文件和目录,组织不会亏待你 命令行,世界尽在掌握 今天的标题是不是有点霸气侧漏呢? 读者:"小编,你为什么每次都要起这么非主流的标题呢?不能愉快地玩耍么?" 小编:"那我问你,老子他为什么要写<道德经>咧?" 读者:"为什么咧?" 小编:"因为老子愿意!" 开个小玩笑轻松一下 O(∩_∩)O~ 没办法,不能不激动,因为我们终于来到了这一刻,

【Web探索之旅】第二部分第二课:服务器语言

内容简介 1.第二部分第二课:服务器语言 2.第二部分第三课预告:框架和内容管理系统 第二部分第二课:服务器语言 介绍了Web的客户端,我们来谈谈Web的服务器端. 既然客户端有客户端的编程语言(HTML,CSS和JS),那么我们服务器端岂能逊色呢,对吧. 服务器端也有不少种编程语言.这些编程语言写成的程序会在服务器端的电脑上被执行. 如果说客户端的语言编写的程序决定了我们的网页的外观,那么服务器端的语言编写的程序决定了网页的功能和如何与用户交互. 你也许会问:"既然我们可以用HTML,CSS和

【Linux探索之旅】第二部分第九课:查找文件,无所遁形

内容简介 1.第二部分第九课:查找文件,无所遁形 2.第二部分测试题 查找文件,无所遁形 这一课不难,但挺重要的. 之前的课程我们见识过了Linux下文件的组织形式是很特别的,跟Windows不一样. 我们也用ls / 这个命令来列出根目录下的所有目录,有/bin,/etc,/var,/home,等等.而这些目录下又有子目录和文件,错综复杂. 这些目录中有一部分是历史遗留的,从Unix时代就有了.问题是:我们如何在这"茫茫文海"中查找我们需要的文件. "人潮人海中,有你有我.