这是创刊于 2018年的父子课堂在线原创 第 100 期
USACO(美国计算机奥林匹克竞赛)——国内学生申请美国大学提升背景的利器。
前情回顾
Hello everyone!我是你们的老朋友小阮老师!今天跟大家分享一句名言:
四月不学习,五月徒伤悲
——渥兹基硕德
什么意思呢?就是说,过完五一小长假,大家基本就要开学了吧(说没有的筒靴不要骗自己了,都是高中生了成熟一点好嘛),有的学校开学第一天干什么呢?期中考试。脑袋还是空的就要期中考试了那还不是徒伤悲吗?
是的,期中考试。如果你的老师没跟你说过这档子事,可能是你们真的没有期中考试,那也可能是他忘(tai)了(jian)说(zha)。anyway,学习什么的搞起来吧!毕竟现在玩得多嗨,成绩出来可能就被打得多惨了!
上一次课中小阮老师带大家学习了变量,大家是否还记得变量是什么?
我们定义了一个变量,就是在计算机内存RAM中开辟一块与这个变量的算术类型相符合的空间。这么一说是不是感觉变量也不深奥了?只要我们在变量被使用之前进行定义,把变量放在赋值语句左侧,别把变量名取成C++关键字,就可以正确使用变量啦!
而我们今天要学习的是变量剩下的内容:声明和定义,以及名字的作用域。今天的课程结束,变量的所有知识点我们都收入囊中了!
声明和定义的区别
我们在程序设计中,时时刻刻都用到变量的定义和变量的声明,那他们都是怎么一回事呢?我们先看两个语句,分别表示定义和声明:
int a ; //定义(定义并声明了变量 a)extern int a; //声明(只是声明了有一个变量 a 存在,具体 a 在哪定义的,需要编译器编译的时候去找)
定义是需要建立存储空间的。例如:int a 在产生的时候就已经建立了存储空间。
声明是不需要建立存储空间的。 例如:extern int a 其中变量a是在别的文件中定义的。
定义也是声明,extern声明不是定义。
是不是还有点迷糊?我们用类比的方法来理解:在大型程序设计中,
编写多个源文件 ☞
我们同时建造多个大楼
在某源文件中定义一个函数 ☞
买了把锤子放在大楼A的一个角落,它是占用了大楼空间的。
在别的源文件中声明了这个函数 ☞
我们知道有一把锤子在大楼A放着),所以我们在墙上贴了个条“锤子在大楼A“,需要的时候直接去拿就好了!
一个变量只能在一个源文件中被定义 ☞
一把工具当然不可能同时放在两个楼里!
这个变量在任何源文件中都可以被声明 ☞
但是我们可以在所有的大楼墙上都贴纸条!
这么理解定义和声明,就清楚明白啦!
声明和定义的语法
如何定义变量,上一次课我们已经有详细的介绍,那么如果想声明一个变量而非定义它,就在变量名前添加关键字extern,而且不要显式地初始化变量(给变量赋值):
int a ; //定义(定义并声明了变量 a,int可以换成其他)extern int a; //声明(只是声明了有一个变量 a 存在,具体 a 在哪定义的,需要编译器编译的时候去找,int同样可换)
但是注意,无论是否带有extern,语句中如果包含初始值就不再是声明,而变成定义了哦!也就是说,任何包含了显式初始化的声明即成为定义。我们能给由extern关键字标记的变量赋个初始值,但是这么做也就抵消了extern的作用。
int a = 0; //定义(定义并声明了变量 a)extern int a = 0; //定义(定义并声明了变量 a)
声明的变量必须与该变量被定义时的类型一致!如果我们在某个源文件中定义:
int a ;
声明变量a时就必须是
extern int a;
int不可以换成其他的类型,否则C++就无法找到变量a啦!
名字的作用域
筒靴们可能对“名字”表示不理解,其实,我们定义一个变量
int a = 0;
那么a就是这个变量的名字啦!就这么简单!那我们定义了这样一个变量之后,它在整个函数的哪一部分起作用呢?是整个函数,还是包含此变量的某一部分呢?我们用一段程序来跟大家解释:
# include int main(){int sum=0;for (intval =1: val <=10; ++val)sum+=val; std: cout << "Sum of 1 to 10 inclusive is"<< sum << std: endl;return 0}……
这段程序定义了3个变量:main、sum和val。
名字main定义于所有花括号之外,它和其他大多数定义在函数体之外的名字一样拥有全局作用域。一旦声明之后,全局作用域内的名字在整个程序的范围内都可使用。作用范围:
int main(){int sum=0;for (int val =1: val <=10; ++val)sum+=val;std: cout << "Sum of 1 to 10 inclusive is"<< sum << std: endl;return 0}……
名字sum定义于main函数所限定的作用域之内,从声明sum开始直到main函数结束为止都可以访问它,但是出了main函数所在的块就无法访问了,因此说变量sum拥有局部作用域。作用范围:
int sum=0;for (int val =1: val <=10; ++val)sum+=val;std: cout << "Sum of 1 to 10 inclusive is"<< sum << std: endl;return 0
名字val定义于for语句内,在for语句之内可以访问va1,但是在main函数的其他部分就不能访问它了。作用范围:
for (int val =1: val <=10; ++val)sum+=val;
在编程的时候,我们允许在内层作用域中重新定义外层作用域的名字,C++采用的是覆盖的原则,它往往采取最新一次的定义。但是如果全局变量使用了某个名字,还是要避免局部变量使用相同的名字哦!
*本文原创作者:父子课堂在线小阮老师,浙江大学在读研究生,AMC/USACO专项教师
选择C++的必要性
同学们有没有想过,我们为什么首选带大家学习C++,以及鼓励大家参加竞赛的时候要用C++完成呢?小问号你是不是有很多朋友?
我们先来看一下2020 USACO月赛对于选手使用语言情况的公开数据:
In total, there were 13498 graded submissions, broken down by language as follows:
4594 C++11 4070 Java 2959 C++ 1649 Python 3.4.0 144 Python 2.7.6 81 C 1 Pascal
其中C++11是C++的新标准,和第三名C++同属于C++,加起来,总数远超位居第二的Java!
C++ 是USACO竞赛中使用最多的语言,这是有原因的,USACO竞赛会要求代码的时间和空间使用效率,即使你的代码是正确的,如果执行时间上超出规定时间,或者空间使用上超出规定空间,都不能算是通过。特别是在USACO的高级别题目中,这些题目都需要进行大量的计算,这时候选择C++ 就有很大帮助了。
C++ 语言就是一门很高效的语言,运用得当,可以使用它写出非常高效的代码,同时,它还引入了面向对象的理念,可以便捷的使用数据结构和算法库,使得代码编写更加方便。
并且,如果想同时参加国内信息学奥赛(NOIP)的选手,就一定要选择C++ 了,因为国内的竞赛不像国外支持这么多种语言,它后续只支持C++ 了。