Logo
Section 1 / 6

生命周期

本节课我们讨论变量和参数的生命周期。

导入

生命周期

本节课我们讨论变量和参数的生命周期。

章节概览

我们将很快学习结构体(structs),这是程序员定义特定于应用程序类型的基本特性。结构体 用于将基本类型和其他结构体组合起来,以定义符合程序特殊需求的高级类型。在了解结构体之后,你将学习类(classes),它们是 D 语言面向对象编程特性的基础。

在深入结构体和类之前,我们先讨论一些重要的概念。这些概念将帮助你理解结构体和类,以及它们之间的区别。

我们将把程序中代表某个概念的任何数据片段称为变量。在某些地方,我们会特别将 struct 和 class 变量称为对象。但在本章中,我们仍继续将这两者统称为变量。

尽管本章仅涵盖基本类型、切片和关联数组,但这些概念同样适用于用户自定义类型。

## 变量的生命周期

从变量被定义到其被 终结 的这段时间,称为该变量的生命周期。虽然对许多类型来说,不可用与终结是同时发生的,但这并非必然。

让我们回顾一下变量何时变得不可用。在简单情况下,当退出变量定义的作用域时,该变量即变为不可用。

以下是一个提醒示例:

Course Image
1void speedTest() { 2 int speed; // 单个变量... 3 4 foreach (i; 0 .. 10) { 5 speed = 100 + i; // ... 取了 10 个不同的值。 6 } 7 write(speed); 8} // ← 'speed' 在此点之后不再可用。

在上述代码中,speed 变量的生命周期在退出 speedTest() 函数时结束。代码中只有一个变量,它从 100 到 109 共取了十个不同的值。

然而,下面这段代码在变量生命周期方面与前一段有显著不同:

1void speedTest() { 2 foreach (i; 0 .. 10) { 3 int speed = 100 + i; // 十个独立的变量。 4 // ... 5 } // ← 每个变量的生命周期在此处结束。 6 write(speed); 7}

这段代码中有十个独立的变量,每个变量只取一个值。在每次循环迭代中,都会创建一个新的变量,其生命周期在每次迭代结束时终止。

参数的生命周期

参数的生命周期取决于其限定符:

  • ref:此参数只是调用函数时指定的实际变量的别名。ref 参数不会影响实际变量的生命周期。
  • in:对于值类型,in 参数的生命周期从进入函数开始,到退出函数结束。对于引用类型,其生命周期与 ref 相同。
  • out:与 ref 类似,此参数也是实际变量的别名。唯一的区别在于,变量在进入函数时会自动被设置为 .init 值。
  • lazy:lazy 参数的生命周期从其被实际使用时开始,到使用结束时终止。

下面的例子展示了这四种参数类型,并通过程序注释说明了它们的生命周期:

1void main() { 2 int main_in; /* main_in 的值被复制到参数中。 */ 3 4 int main_ref; /* main_ref 作为自身传入函数。 */ 5 6 int main_out; /* main_out 作为自身传入函数。进入函数时其值被设为 int.init。 */ 7 8 foo(main_in, main_ref, main_out, aCalculation()); 9} 10 11void foo( 12 in int p_in, /* p_in 的生命周期从进入函数开始,到退出函数结束。 */ 13 14 ref int p_ref, /* p_ref 是 main_ref 的别名。 */ 15 16 out int p_out, /* p_out 是 main_out 的别名。进入函数时其值被设为 int.init。 */ 17 18 lazy int p_lazy) { /* p_lazy 的生命周期从被使用时开始,到使用结束时终止。每次在函数中使用 p_lazy 时,都会通过调用 aCalculation() 重新计算其值。 */ 19 // ... 20} 21 22int aCalculation() { 23 int result; 24 // ... 25 return result; 26}

简介

基本操作