C++的定义、声明和赋值到底是什么?

16

我倾向于将“define”、“declare”和“assign”这些词互换使用,但这似乎会冒犯一些人。这种做法是否合理?我是否应该只在第一次给变量赋值时使用“declare”这个词?或者这其中还有更多需要注意的事项吗?

8个回答

40

定义是描述值或函数的地方,即编译器或程序员准确告知它是什么的地方,例如:

int foo()
{
  return 1;
}

int var; // or, e.g. int var = 5; but this is clearer.

声明告诉编译器或程序员函数或变量的存在。例如:

int foo();
extern int var;

赋值是指使用 = 操作符将变量的值设置为特定的值。例如:

a = b;
a = foo();

3
实际上,我认为"int var;"是定义,"int var = 5;"是定义和赋值的组合。在C语言中,任何创建对象空间的操作都可以看作是定义。我会点赞你的回答,也许你会改变它,也许不会,但这是迄今为止最好的回答。 - paxdiablo

9

定义和声明类似,但赋值则非常不同。

这里我正在声明(或定义)一个变量:

int x;

这里我正在为该变量分配一个值:

x = 0;

这里我会在一个语句中同时完成两个操作:

int x = 0;

注意

并非所有语言都支持在一条语句中声明和赋值:

T-SQL

declare x int;
set x = 0;

有些编程语言要求在声明变量时为其赋值。这个要求使得编程语言的编译器或解释器可以推断出变量的类型:

Python

x = 0

我来细说一下——Python没有任何形式的“声明”。类和函数是“定义”的,变量在赋值时创建。你实际上并不需要“声明”变量,因为它们只是分配给对象的名称。 - S.Lott
这是一个很好的观点 - 作为一个吹毛求疵的人,我很欣赏这种区别 :) - Andrew Hare
更挑剔的是:Python 实际上并不执行任何类型推断,它是动态类型的。只有在变量具有类型时才需要类型推断。这是有效的 Python 代码,并说明了我的观点的影响:“x = 5; x =“str””。 - Magnus Hoff
我建议要么使用另一种语言作为示例(比如Haskell或C#的var),要么就删除"推断"这句话。不管怎样,这只是挑剔而已 :) - Magnus Hoff
2
声明和定义在编程中并不相似(即使在某些语言中没有进行区分)。请参见下面jheriko的答案。 - Ian Goldby
使用简单类型(如整数)来提供答案可能会让人感到困惑。术语“定义”可能不适用于它们,如果是这样的话,就无法使用简单类型来解释区别。 - Sam Hobbs

6

使用正确的术语非常重要,否则人们将不知道你在谈论什么,或者错误地认为你不知道自己在说什么。


5

这些术语在各种编程语言的标准中通常具有精确的含义。在这种情况下,它们不应混淆。

例如,在 C 语言中:

  • 一个函数只能被定义一次(即当您说明它的功能时),但在此之前可以进行声明(即说明它需要哪些参数和返回什么类型)。

  • 同样,变量在声明时指定其类型,每个作用域只会发生一次。但是您可以反复赋值。(某些语言还区分初始化(在声明时给变量赋值)和赋值(稍后更改值))。


4

一般角色: 定义 = 声明 + 保留空间。

定义、声明和赋值有两种情况:

  1. 对于变量。
  2. 对于函数。

对于变量

-- 定义:
告诉编译器为变量保留内存空间。

int x;

--声明:
告诉编译器该变量在其他地方定义。

extern int x;

--任务:
告诉编译器将值存入变量中。

x = 0;

关于 函数:

-- 定义:

int functionDef(int x){
  int x;  
  ...  
  ...  
  ...  
  return x;  
}

-- 声明: 这只是该函数的原型。

int functionDef(int x);

3

这些差异看似微小,但却非常重要。虽然不是每种语言都进行相同的区分,但在C++中,变量声明使得编译器知道了变量的类型和名称。

int i;

变量定义分配存储空间并为变量指定初始值。

i = 1;

您可以将变量声明和定义组合成一个语句,这是常见的做法。

int x = 1;

在函数内声明一个变量也会为该变量分配内存,因此以下代码隐式地将变量 a 定义为其声明的一部分。
int main()
{
    int a;
    return 0;
}

由于变量a是由编译器自动定义的,它将包含分配给它的内存位置中的任何值。这就是为什么在明确分配已知值之前,使用自动变量不安全的原因。

当你改变程序中变量的值时,发生了一次赋值

x = 2;
x++;
x += 4;

函数声明类似于变量声明,它使得函数签名对编译器可见。这样你就可以在源代码中调用一个未定义的函数而不会导致编译错误。

int doSomething(float x);

函数定义指定了函数的返回类型、名称、参数列表和指令。其中前三个元素必须与函数声明匹配。在给定的程序中,函数只能被定义一次。

int doSomething(float x)
{
    if( x < 0 )
    {
        x = -x;
    }
    return static_cast<int>(x);
}

您可以将函数声明和定义合并为一个,但必须在程序中任何地方调用该函数之前这样做。

我曾以为变量的声明会分配存储空间。除非你提供了一个初始化值或者赋予新的值,否则你得到的只是这个空间里的垃圾。你只能在声明变量时对它进行初始化。 - Artelius
@Artelius:在大多数情况下,声明包括编译器的隐式定义,这使得声明似乎分配了存储空间。我在我的答案中加入了一个(希望)澄清的补充说明。感谢您指出这一点。 - Bill the Lizard
我投票支持这个答案,因为它是正确的,正如我所学过的。如果不是这样,我真的很想知道为什么。上面的答案声明和定义弄反了。 - lakeweb
i = 1 是一种赋值,而不是定义。要成为定义(例如在其定义翻译单元中先前声明的 extern 变量的定义),它需要类型(赋值组件是可选的)。 - underscore_d

-1

这可能取决于编程语言,正如先前所述。我认为这主要取决于这些词是否用于类等事物。对于这里讨论的大多数数据类型,这个问题可能没有太大关联。在 C++(参见c++ - What is the difference between a definition and a declaration?),一个类或结构体总是有且仅有一个定义,但可以被声明零次或多次。一个类不能在没有定义时被声明。因此,“声明”可能与“使用”同义。

在大多数语言中,像整数这样的简单类型不需要像类那样的定义。


-2

正确答案取决于你所说的语言。计算机语言通常有特定的术语,这要么是由于语言规范,要么是由于围绕该语言形成的社区。COBOL在我使用它的时候,与更主流的编程语言(指更接近语言开发主流而不是主流商业的语言)有很大不同的术语。Forth则发展出了一些奇怪的术语。

如果你知道英语,通常可以从它的正常含义中得到一个词的含义,但不要过于依赖。同样,不同语言或语言社区中的特定词语也是如此。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接