我不明白两者的意义。


当前回答

经验法则:

声明告诉编译器如何解释内存中的变量数据。这是每个访问都需要的。 定义保留内存以使变量存在。这必须在第一次访问之前发生一次。

其他回答

为了理解声明和定义之间的区别,我们需要查看程序集代码:

uint8_t   ui8 = 5;  |   movb    $0x5,-0x45(%rbp)
int         i = 5;  |   movl    $0x5,-0x3c(%rbp)
uint32_t ui32 = 5;  |   movl    $0x5,-0x38(%rbp)
uint64_t ui64 = 5;  |   movq    $0x5,-0x10(%rbp)
double   doub = 5;  |   movsd   0x328(%rip),%xmm0        # 0x400a20
                        movsd   %xmm0,-0x8(%rbp)

这只是定义:

ui8 = 5;   |   movb    $0x5,-0x45(%rbp)
i = 5;     |   movl    $0x5,-0x3c(%rbp)
ui32 = 5;  |   movl    $0x5,-0x38(%rbp)
ui64 = 5;  |   movq    $0x5,-0x10(%rbp)
doub = 5;  |   movsd   0x328(%rip),%xmm0        # 0x400a20
               movsd   %xmm0,-0x8(%rbp)

正如你所看到的,没有任何变化。

声明与定义不同,因为声明提供的信息仅供编译器使用。例如uint8_t告诉编译器使用asm函数movb。

看到:

uint def;                  |  no instructions
printf("some stuff...");   |  [...] callq   0x400450 <printf@plt>
def=5;                     |  movb    $0x5,-0x45(%rbp)

声明没有等价的指令,因为它不是要执行的东西。

此外,声明告诉编译器变量的作用域。

我们可以说,声明是编译器用来确定正确使用变量的信息,以及某些内存属于某个变量多长时间。

声明意味着给变量命名和类型(在变量声明的情况下),例如:

int i;

或者将名称、返回类型和参数类型赋给一个没有函数体的函数(在函数声明的情况下),例如:

int max(int, int);

而定义意味着给变量赋值(在变量定义的情况下),例如:

i = 20;

或者为函数提供/添加函数体(功能)被称为函数定义,例如:

int max(int a, int b)
{
   if(a>b)   return a;
   return b;  
}

许多时间声明和定义可以一起完成:

int i=20;

and:

int max(int a, int b)
{
    if(a>b)   return a;
    return b;    
} 

在上述情况下,我们定义并声明变量i和函数max()。

声明是在未分配值或对象的情况下创建原语或对象引用变量或方法。 int; Final int a;

定义意味着分别为值或对象赋值 Int a =10;

初始化意味着为各个变量或对象分配内存。

我最喜欢的例子是int Num = 5这里你的变量是1。定义为int 2。声明为Num和3。实例化值为5。我们

定义对象的类型,可以是内置的,也可以是类或结构。 声明一个对象的名字,这样任何有名字的东西都被声明了,包括变量、函数等。

类或结构允许您在以后使用时更改对象的定义方式。例如

可以声明没有特别定义的异构变量或数组。 在c++中使用偏移量可以定义一个没有声明名称的对象。

当我们学习编程时,这两个术语经常被混淆,因为我们经常同时做这两个。

声明引入标识符并描述其类型,可以是类型、对象或函数。声明是编译器接受对该标识符的引用所需要的。这些是声明:

extern int bar;
extern int g(int, int);
double f(int, double); // extern can be omitted for function declarations
class foo; // no extern allowed for type declarations

定义实际上实例化/实现了这个标识符。它是链接器为了将引用链接到这些实体所需要的。这些是对应于上述声明的定义:

int bar;
int g(int lhs, int rhs) {return lhs*rhs;}
double f(int i, double d) {return i+d;}
class foo {};

定义可以用在声明的地方。

标识符可以根据需要任意声明。因此,以下代码在C和c++中是合法的:

double f(int, double);
double f(int, double);
extern double f(int, double); // the same as the two above
extern double f(int, double);

但是,它必须只定义一次。如果您忘记定义某个已经声明和引用的东西,那么链接器就不知道要链接到什么地方,并抱怨缺少符号。如果定义一个东西不止一次,那么链接器就不知道要链接引用哪个定义,并抱怨重复的符号。


由于在c++中什么是类声明和类定义的争论不断出现(在对其他问题的回答和评论中),我将在这里粘贴一段来自c++标准的引用。 在3.1/2,c++ 03说:

声明是定义,除非它[…是类名声明[…]。

3.1/3然后给出了几个例子。其中:

[Example: [...]
struct S { int a; int b; }; // defines S, S::a, and S::b [...]
struct S; // declares S
—end example

总结一下:c++标准考虑结构体x;是一个声明和结构x {};一个定义。(换句话说,“前向声明”是用词不当,因为在c++中没有其他形式的类声明。)

感谢litb (Johannes Schaub)在他的回答中找出了实际的章节和诗句。