初始化,定义,声明变量之间的区别


79

阅读问题之后,我知道了声明和定义之间的区别。那么,这是否意味着定义等于声明加上初始化?


1
初始化用于变量。定义也可以应用于定义主体的功能。
FKaria 2014年

那么,您的意思是说变量是对的。
托尼

Answers:


98

宣言

通常,声明是指在程序中引入新名称。例如,您可以通过描述新函数的“签名”来声明它:

void xyz();

或声明不完整的类型:

class klass;
struct ztruct;

最后但并非最不重要的一点是,声明一个对象:

int x;

在C ++标准中,在§3.1/ 1中将其描述为:

声明(第7条)可以在翻译单元中引入一个或多个名称,也可以重新声明以前声明引入的名称。

定义

定义是先前声明的名称的定义(或者可以是定义和声明)。例如:

int x;
void xyz() {...}
class klass {...};
struct ztruct {...};
enum { x, y, z };

具体而言,C ++标准在第3.1 / 1节中将其定义为:

声明是一个定义,除非它在未指定函数主体的情况下声明函数(8.4),它包含extern说明符(7.1.1)或链接规范25(7.5),并且既不初始化也不是函数体,而是声明一个类定义(9.2,9.4)中的静态数据成员,它是类名声明(9.1),它是不透明枚举声明(7.2),它是模板参数(14.1),它是参数-不是函数定义的声明器的函数声明器中的声明(8.3.5),或者它是typedef声明(7.1.3),别名声明(7.1.3),using声明(7.3。)。 3),static_assert声明(第7章),属性声明(第7章),空声明(第7章)或using伪指令(7.3.4)。

初始化

初始化是指在构造时值的“赋值”。对于type的通用对象,T通常采用以下形式:

T x = i;

但是在C ++中可以是:

T x(i);

甚至:

T x {i};

使用C ++ 11。

结论

那么,这是否意味着定义等于声明加上初始化?

这取决于。关于你在说什么。如果您在谈论一个对象,例如:

int x;

这是没有初始化的定义。相反,以下是带有初始化的定义:

int x = 0;

在某些情况下,谈论“初始化”,“定义”和“声明”是没有意义的。例如,如果您在谈论一个函数,初始化的意义并不大。

因此,答案是否定的:定义并不自动意味着声明加初始化。


12
不完全int x;是:定义和声明。
Angew不再为2014年

2
@Angew,谢谢,我添加了更完整的定义
Shoe

我认为OP在他的帖子中提到的问题很好地回答了定义和声明。但是最初的问题是So does it mean definition equals declaration plus initialization
Tahlil 2014年

@Tahlil,添加了一个结论。感谢您通知我。
2014年

3
@Tony我认为(如果我错了,请有人纠正我,以便我学习)'extern int x'只是一个声明,意味着该定义在其他地方可以找到。尽管“ int x”实际上是用随机垃圾值指定的,但实际上是对其进行定义的,除非您像“ int x = 5”那样专门对其进行初始化。
臭小子

39

宣言说“这东西存在于某处”:

int foo();       // function
extern int bar;  // variable
struct T
{
   static int baz;  // static member variable
};

定义说:“这东西存在于此;为此做记忆”:

int foo() {}     // function
int bar;         // variable
int T::baz;      // static member variable

在定义对象时,初始化是可选的,并说“这是事物的初始值”:

int bar = 0;     // variable
int T::baz = 42; // static member variable

有时有可能在声明时代替:

struct T
{
   static int baz = 42;
};

…但这正在涉及更复杂的功能。


很好地解释了,除了初始化要比这复杂得多。(如果就这么简单,就不会是C ++。)初始化包括诸如使用静态生存期对变量进行零初始化,默认构造函数以及所显示内容之类的事情。(更令人困惑的是:在C语言中,初始化可能是第一次将变量分配给它;例如,在诸如“获取未初始化变量的值”之类的语句中。如果其中某些内容也误入C ++。)
James Kanze 2014年

哦,在某些特殊情况下,C ++允许在声明中指定初始化。
James Kanze 2014年

1
@JamesKanze:出于这些目的决定保持其超级简单
轨道轻赛

6

对于C,至少根据C11 6.7.5:

声明指定一组标识符的解释和属性。标识符的定义是对该标识符的声明:

  • 对于一个对象,导致为该对象保留存储空间;

  • 对于功能,包括功能主体;

  • 对于枚举常量,是标识符的(唯一)声明;

  • 对于typedef名称,是标识符的第一个(或唯一)声明。

根据C11 6.7.9.8-10:

初始化程序指定存储在对象中的初始值...如果没有自动存储的对象未显式初始化,则其值不确定。

因此,从广义上讲,声明引入了标识符并提供了有关它的信息。对于变量,定义是为该变量分配存储空间的声明。

初始化是要存储在对象中的初始值的指定,它不一定与您第一次为其明确分配值时的初始值相同。定义变量时,变量是否具有值,无论您是否明确为其赋值。如果您未明确为其提供值,并且该变量具有自动存储功能,则它将具有初始值,但该值将不确定。如果具有静态存储,则会根据类型隐式初始化(​​例如,将指针类型初始化为空指针,将算术类型初始化为零,依此类推)。

因此,如果您在定义自动变量时未为其指定初始值,例如:

int myfunc(void) {
    int myvar;
    ...

您正在定义它(因此也要声明它,因为定义是声明),而不是初始化它。因此,定义不等于声明加初始化。


在C ++中,初始化有很大不同。(C还等效于具有静态生命期的对象的零初始化。)
James Kanze 2014年

@JamesKanze:是的,不幸的是,这个问题同时用C和C ++进行了标记,这对于区别它们的那些点不是很有帮助。
克劳曼2014年

相当。对于兼容类型,C ++的意图(至少是最初的目的)是它们的行为与C中的行为相同;实际上,我认为在语言本身兼容的所有情况下,它们的行为仍然相同。但是用来定义这种行为的措辞却大不相同。
James Kanze 2014年

1

“所以这意味着定义等于声明加上初始化。”

不一定,您的声明可能没有初始化任何变量,例如:

 void helloWorld(); //declaration or Prototype.

 void helloWorld()
 {
    std::cout << "Hello World\n";
 } 
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.