C++ 参数分类
在C++中,函数参数可以分为以下几种分类:
位置参数
位置参数是指按照定义的顺序传递给函数的参数。在函数调用时,实参的顺序必须与函数声明或定义中形参的顺序相对应。
示例代码:
int add(int a, int b) { return a + b; } int main() { int result = add(5, 3); return 0; }
在上述示例中,add
函数接收两个位置参数 a
和 b
,并返回它们的和。在函数调用 add(5, 3)
中,5被赋给了参数 a
,3 被赋给了 参数 b
。
默认参数:
有默认值的参数,可以不传;一般刚在参数列表的最后;
默认参数是指在函数声明或定义时为参数提供默认值。如果函数调用时没有提供对应参数的值,则将使用默认值作为实参。
示例代码:
int multiply(int a, int b = 2) { return a * b; } int main() { int x = 5; int result1 = multiply(x); // 使用默认参数,相当于 multiply(x, 2) int result2 = multiply(x, 3); // 不使用默认参数,直接传递实参 return 0; }
在上面的示例中,multiply
函数的第二个参数 b
设置了默认值 2。在函数调用 multiply(x)
中,由于没有提供第二个参数的值,因此将使用默认值 2。而在函数调用 multiply(x, 3)
中,直接传递了实参 3。
可变参数(变参函数)
关键在于:参数数量可变;
可变参数是指函数可以接受数量可变的参数。在C++中,通过使用标准库中的可变参数模板 std::initializer_list
来实现可变参数的功能。
示例代码:
double average(std::initializer_list<double> nums) { double sum = 0; for (auto num : nums) { sum += num; } return sum / nums.size(); } int main() { double avg1 = average({1.2, 2.4, 3.6}); double avg2 = average({5.1, 6.2, 7.3, 8.4, 9.5}); return 0; }
上述示例中的 average
函数可以接受不定数量的 double 类型参数,并计算它们的平均值。在函数调用时,可以使用花括号 {}
来初始化 std::initializer_list
并传递参数。
借助不同的参数分类方式,可以提供更灵活和多样化的函数调用方式。
C++函数参数值传递和引用传递
常规分类
在 C++ 中,函数的参数传递方式可以分为值传递和引用传递。这两种方式在参数的传递方式和对实参的修改能力上有所不同。
值传递(Pass by Value):
值传递是指将实参的值复制给形参,在函数中对形参的修改不会影响实参本身。
示例代码:
void modifyValue(int num) { num = 10; } int main() { int x = 5; modifyValue(x); // x的值仍然是5,没有被修改 return 0; }
在上述示例中,modifyValue
函数使用值传递方式接收参数 num
。在函数内部对 num
的修改不会影响到实参 x
的值。
使用值传递的特点:
- 在函数中对参数进行修改不会影响原始的实参。
- 函数会创建形参的副本,因此可能会占用额外的内存。
- 可以避免函数对实参的修改,从而保持实参的不变性。
引用传递(Pass by Reference):
引用传递是指将实参的引用传递给形参,在函数中对形参的修改会同时修改实参。
示例代码:
void modifyValue(int& num) { num = 10; } int main() { int x = 5; modifyValue(x); // x的值被修改为10 return 0; }
在上述示例中,modifyValue
函数使用引用传递方式接收参数 num
。在函数内部对 num
的修改也会反映到实参 x
上,使其值变为了 10。
使用引用传递的特点:
- 函数可以直接修改实参的值,避免了值传递的额外内存开销。
- 可以通过引用传递对象来避免对象的复制构造函数的调用,提高效率。
- 如果希望通过函数修改实参的值,可以使用引用传递。
需要注意的是,使用引用传递时需要确保传递的参数不会过早地销毁,否则引用将指向无效的内存。
总结来说,值传递将实参的值复制给函数的形参,对形参的修改不会影响实参本身;引用传递将实参的引用传递给函数的形参,对形参的修改会同时修改实参。
C++ 引用参数的分类
在C++中,引用传递又可以根据是否具有 const
限定符进行分类。引用参数的分类如下:
非常量引用参数
可变的引用参数;
非常量引用参数是使用 &
符号定义的,它允许函数修改传递给它的实参,并且对应的实参也会被修改。
示例代码:
void changeValue(int& num) { num = 10; } int main() { int x = 5; changeValue(x); // x的值被修改为10 return 0; }
在上述示例中,changeValue
函数的参数 num
是一个非常量引用。在函数内部对 num
的修改直接反映到了实参 x
上,使得其值变为了 10。
使用非常量引用参数的场景:
- 当函数需要修改传递进来的参数的值时。
- 当将大型对象作为参数传递给函数时,通过引用传递可以避免对象的复制。
常量引用参数(不可变的应用参数)
常量引用参数是使用 const
关键字和 &
符号定义的,它确保函数无法修改传递给它的实参,只能读取。
示例代码:
void printValue(const int& num) { std::cout << "Value: " << num << std::endl; } int main() { int x = 5; printValue(x); return 0; }
在上述示例中,printValue
函数的参数 num
是一个常量引用。函数内部无法修改 num
的值,只能读取。因此,printValue
函数只会打印实参 x
的值,不会对实参进行修改。
使用常量引用参数的场景:
- 当函数不需要修改传递进来的参数的值时,可以避免不必要的变动。
- 当将大型对象作为参数传递给函数时,通过常量引用传递可以避免对象的复制,并提高效率。
非常量引用参数允许修改传递给函数的实参,而常量引用参数只能读取实参的值,不能进行修改。选择哪种引用参数取决于函数是否需要修改实参的值。
C++参数引用的方法分类
在 C++ 中,参数引用还可以可以根据语法和修改能力进行分类。以下是几种常见的参数引用方法分类:
左值引用(Lvalue references):
左值引用使用 &
符号定义,在函数参数列表中表示对传递给函数的变量进行引用。该引用可以修改传递给函数的变量。
示例代码:
void changeValue(int& num) { num = 10; } int main() { int x = 5; changeValue(x); // x的值被修改为10 return 0; }
在上述示例中,changeValue
函数的参数 num
是一个左值引用。通过引用传递,函数可以修改实参 x
的值,将其更改为 10。
常量左值引用(Const Lvalue references):
常量左值引用使用 const
关键字和 &
符号定义,允许函数引用传递给它们的变量,并且可以读取但不能修改这些变量的值。
示例代码:
void printValue(const int& num) { std::cout << "Value: " << num << std::endl; } int main() { int x = 5; printValue(x); return 0; }
在上述示例中,printValue
函数的参数 num
是一个常量左值引用。函数可以引用传递的实参 x
,但只能读取它的值,不能修改。
右值引用(Rvalue references):
右值引用使用 &&
符号定义,允许将右值绑定到引用上。右值引用通常用于实现移动语义和完美转发。
示例代码:
void changeValue(int&& num) { num = 10; } int main() { int x = 5; changeValue(std::move(x)); // 此时x的值是未定义的 return 0; }
在上述示例中,changeValue
函数的参数 num
是一个右值引用。通过使用 std::move
将左值 x
转换为右值引用传递给函数,然后在函数内部修改了该值。