导入
函数参数
本课讲解函数参数,并说明为什么参数总是被复制。
函数参数
本章的一些概念在课程早期已经出现过。例如,我们在foreach 循环课程中学习的 ref 关键字,使得在 foreach 循环中可以直接访问实际元素,而不是它们的副本。
此外,我们之前已经讨论过 const 和 immutable 关键字,以及值类型和引用类型之间的区别。我们编写过利用参数来产生结果的函数。例如,下面这个函数在计算中使用了它的参数:
1double weightedAverage(double quizGrade, double finalGrade) { 2 return quizGrade * 0.4 + finalGrade * 0.6; 3}
该函数通过取测验成绩的 40% 和期末成绩的 60% 来计算加权平均分。以下是它的使用示例:
1import std.stdio; 2 3double weightedAverage(double quizGrade, double finalGrade) { 4 return quizGrade * 0.4 + finalGrade * 0.6; 5} 6 7void main() { 8 9 int quizGrade = 76; 10 int finalGrade = 80; 11 writefln("加权平均分: %2.0f", weightedAverage(quizGrade, finalGrade)); 12}
参数总是被复制
在上面的代码中,两个变量作为实参传递给 weightedAverage() 函数。函数使用其参数。这可能会让人误以为函数直接使用了传入的实际变量。实际上,函数使用的是这些变量的副本。
这一点非常重要,因为修改一个参数只会改变副本本身。这一点可以通过以下尝试修改参数(即产生副作用)的函数看出。假设我们编写了一个函数用于降低游戏角色的能量值:
1void reduceEnergy(double energy) { 2 energy /= 4; 3}
以下是测试 reduceEnergy() 的程序:
1import std.stdio; 2 3void reduceEnergy(double energy) { 4 energy /= 4; 5} 6 7void main() { 8 double energy = 100; 9 10 reduceEnergy(energy); 11 writeln("新能量值: ", energy); 12}
尽管 reduceEnergy() 将其参数的值减少到原来的四分之一,但 main() 中的 energy 变量并未发生变化。原因是 main() 中的 energy 变量与 reduceEnergy() 的 energy 参数是两个独立的变量;参数只是 main() 中变量的一个副本。
为了更清楚地观察这一现象,我们加入一些 writeln() 输出语句:
1import std.stdio; 2 3void reduceEnergy(double energy) { 4 writeln("进入函数时 : ", energy); 5 energy /= 4; 6 writeln("离开函数时 : ", energy); // 参数值已改变 7} 8 9void main() { 10 double energy = 100; 11 12 writeln("调用函数时 : ", energy); 13 reduceEnergy(energy); 14 writeln("从函数返回后 : ", energy); // 变量值保持不变 15}
在下一课中,我们将看到引用变量不会被复制。