变量定义:用于为变量分配存储空间,还可为变量指定初始值。程序中,变量有且仅有一个定义。
变量声明:用于向程序表明变量的类型和名字。
定义也是声明,extern声明不是定义
定义也是声明:当定义变量时我们声明了它的类型和名字。
extern声明不是定义:通过使用extern关键字声明变量名而不定义它。
[注意]
变量在使用前就要被定义或者声明。
在一个程序中,变量只能定义一次,却可以声明多次。
定义分配存储空间,而声明不会。
C++程序通常由许多文件组成,为了让多个文件访问相同的变量,C++区分了声明和定义。变量的定义(definition)用于为变量分配存储空间,还可以为变量指定初始值。在程序中,变量有且仅有一个定义。
声明(declaration)用于向程序表明变量的类型和名字。定义也是声明:当定义变量的时候我们声明了它的类型和名字。可以通过使用extern声明变量名而不定义它。不定义变量的声明包括对象名、对象类型和对象类型前的关键字extern。
extern声明不是定义,也不分配存储空间。事实上它只是说明变量定义在程序的其他地方。程序中变量可以声明多次,但只能定义一次。
只有当声明也是定义时,声明才可以有初始化式,因为只有定义才分配存储空间。初始化式必须要有存储空间来进行初始化。如果声明有初始化式,那么它可被当作是定义,即使声明标记为extern。
任何在多文件中使用的变量都需要有与定义分离的声明。在这种情况下,一个文件含有变量的定义,使用该变量的其他文件则包含该变量的声明(而不是定义)。
现在来讨论一下定义和声明的区别。C++primer的解释是这样的:
变量的定义(definition):用于为变量分配存储空间,还可以为变量指定初始值。在一个程序中,变量有且仅有一个定义;
变量的声明(declaration):用于向程序表明变量的类型和名字。定义也是声明:当定义变量时我们声明了它的类型和名字。可以通过使用extern关键字声明变量名而不定义它。
以上解释讲得还是比较清楚的,有分配空间的叫定义,没分配空间的叫声明。好吧,你不知道什么时候分配什么时候没分配。让我们换一种说法。
“定义也是声明”,这说明声明包括定义。所以诸如int aextern int a之类的一定是声明。那是不是定义还要接着往下看;
如果程序前面都没有出现过a这个变量,这时你要使用a,你必须让程序知道你要使用a这个变量了。这时候你写入int a以前没有a这个变量的,现在程序为了记住它,就得为他分配空间,于是这是个定义。
如果程序包含的其他文件里已经出现过a了,这证明程序已经为a分配内存,这时你要使用a就方便很多了。你只需要告诉程序,这个a在其他地方定义过了,于是你写入extern int a
对于int a来说,它既是定义又是声明;对于extern int a来说,它是声明不是定义。一般为了叙述方便,把建立存储空间的声明称定义,而不把建立存储空间的声明称为声明.
[引申阅读]探讨下c++的声明和定义问题,关于extern
c++primer第四版中,53页的习题2.18中问到,extern std::string name是属于声明还是定义?答案说的是声明。不过我认为,string类中有默认构造函数,如果该语句在函数外,那么则会自动获得储存空间,将name定义为空字符串,不知各位有何高见?
问题补充:
感谢回答我的关于extern的问题,可是还是没想通。正如一楼举的例子extern std:tring name("Zhang3Li4")我认为extern std::string name和那句是一样的 .因为标准库中的string是有默认构造函数的,若后面什么都没有的话,就初始为空字符串
------
我刚才做了一个实验:
//a.cpp
#include <string>
std::string i
//b.cpp
#include <iostream>
#include <string>
extern std::string i
int main ()
{
std::cout <<i <<std::endl
}
运行结果为:
(上面是一空行:由于末尾用了endl)
如果没有a.cpp这个文件,运行出错
这是一对实验(有没有a.cpp文件)
可得出这样的结论:
a.cpp中std::string i是定义(本来就是)
b.cpp中extern std::string i则是声明(你的问题)
先别急,这只是实验结果。我们还需要理论依据,那么下面就试着解释一下:
下面是另一个例子(也是第二个实验)
你应该知道内置类型(int等)如果作为全局变量时,定义的同时也就初始化了(一个内置类型有其对应的默认值;如果你将自定义类型也看成内置类型,那么就等于说,一个自定义类型有其对应的默认值(由默认构造函数完成))。如
//c.cpp
int i
//d.cpp
#include <iostream>
extern int i
int main ()
{
std::cout <<i <<std::endl
}
那么在这里int i就是定义(并且初始化了i,初始值为0)
因而输出结果为
0
//这个实验的运行结果符合理论依据。
(我使用的编译器是visual studio 2008)
从这两个实验来看:(将两个“默认”等同起来)
int i
std::string i
都可以作为初始化i的定义性语句。
那么
extern int i
extern std::string i
也具有定义行为(这个很明显与extern的用法相悖)
在以上两个试验中:int 与 string 有“区别”吗?所有的代码都一样只不过把std::string 换成了 int而已!如果你能解释int的情况,那么我想std::string问题也就迎刃而解了!
于是我个人总结出一个结论:
不论是内置类型还是自定义类型,前面有extern关键字,如果没有显式地初始化参数(即就是自定义类型的默认构造函数被extern屏蔽了,不起初始化的作用),那么就按声明对待。
可能我的描述很混乱,希望你好好看看上面的例子,就明白了!
注意:从这里可以看出来默认构造函数的特殊性!
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)