C++

C++ 知识量:19 - 82 - 316

6.2 参数传递><

传值参数- 6.2.1 -

在C++中,函数的参数传递方式主要有两种:传值(pass by value)和传引用(pass by reference)。

传值参数是指函数接收的是参数值的副本,也就是说,函数对参数的任何改动都仅限于函数内部,不会影响到原始变量。

以下是一个简单的例子:

#include <iostream>  
  
void increment(int x) {  
    x = x + 1;  
}  
  
int main() {  
    int y = 5;  
    increment(y);  
    std::cout << y << std::endl; // 输出:5  
    return 0;  
}

在这个例子中,定义了一个名为 increment 的函数,它接受一个 int 类型的参数 x。在 increment 函数内部,尝试将 x 的值加1。然而,这种修改对于 main 函数中的变量 y 没有任何影响,因为 increment 函数接收的是 y 的副本。这就是传值参数的基本行为。

需要注意的是,传值参数也可以用来传递大型对象,因为这种方式不需要在函数调用时创建新的对象实例。但是,由于传值参数会在函数内部创建一个副本,所以如果对象非常大,可能会导致性能下降。

传引用参数- 6.2.2 -

在C++中,传引用参数是指函数直接接收原始变量的引用,对参数的任何改动都会影响到原始变量。

以下是一个简单的例子:

#include <iostream>  
  
void increment(int& x) {  
    x = x + 1;  
}  
  
int main() {  
    int y = 5;  
    increment(y);  
    std::cout << y << std::endl; // 输出:6  
    return 0;  
}

在这个例子中,定义了一个名为 increment 的函数,它接受一个 int 类型的引用参数 x。在 increment 函数内部,将 x 的值加1。这种修改直接影响了 main 函数中的变量 y,因为 increment 函数接收的是 y 的引用。这就是传引用参数的基本行为。

const形参和实参- 6.2.3 -

在C++中,const关键字可以用于形参和实参来确保函数的参数在函数体内不会被修改。

对于形参而言,使用const关键字可以确保形参在函数体内不会被修改,因此可以用来确保函数的安全性和稳定性。例如,如果一个函数接受一个指向某个数据的指针,但是该数据在函数体内不会被修改,那么可以将该指针的形参定义为const,以防止意外修改数据。

对于实参而言,使用const关键字可以确保实参在函数体内不会被修改,因此可以用来确保函数的正确性。例如,如果一个函数需要传递一个常量值作为参数,那么可以将该参数定义为const,以防止函数体内修改该参数的值。

下面是一个示例代码,演示了如何使用const关键字定义形参和实参:

#include <iostream>  
using namespace std;  
  
void printData(const int* ptr, int data) {  
    cout << "ptr: " << *ptr << endl; // 正确,const 形参可以用来读取数据  
    // cout << "data: " << data << endl; // 错误,const 形参不能用来修改数据  
}  
  
int main() {  
    int a = 10;  
    const int b = 20;  
    printData(&a, b); // 正确,const 实参可以传递给函数  
    return 0;  
}

在上面的代码中,printData()函数的两个参数都是const类型的。第一个参数是一个指向整数的指针,它被定义为const类型,因此不能在函数体内修改该指针所指向的值。第二个参数是一个整数,它被定义为const类型,因此不能在函数体内修改该整数的值。在main()函数中,定义了一个整数变量a和一个常量整数变量b,并将它们的地址和值分别传递给printData()函数。由于b是一个常量整数,因此它可以用作printData()函数的实参。

数组形参- 6.2.4 -

在C++中,数组形参是指函数接受一个数组作为参数。由于数组名实际上是指向数组第一个元素的指针,因此可以将数组名作为函数参数传递给函数。

在函数定义中,数组形参可以声明为任何类型的数组,例如int数组、char数组、float数组等等。在函数体内,可以使用该数组形参来访问数组中的元素。

下面是一个简单的示例代码,演示如何使用数组形参:

#include <iostream>  
using namespace std;  
  
void printArray(int arr[], int size) {  
    for (int i = 0; i < size; i++) {  
        cout << arr[i] << " ";  
    }  
    cout << endl;  
}  
  
int main() {  
    int myArray[5] = {1, 2, 3, 4, 5};  
    printArray(myArray, 5); // 传递数组名和数组大小给函数  
    return 0;  
}

在上面的代码中,定义了一个名为printArray()的函数,该函数接受一个整数数组和该数组的大小作为参数。在main()函数中,定义了一个名为myArray的整数数组,并将其传递给printArray()函数,同时传递数组的大小。在printArray()函数中,使用循环遍历该数组并输出其元素。

处理命令行选项- 6.2.5 -

在C++中处理命令行选项可以通过使用标准库中的getopt()函数来实现。getopt()函数是一个处理命令行选项的库函数,它允许解析传递给程序的命令行参数。

以下是一个简单的示例代码,演示如何使用getopt()函数来处理命令行选项:

#include <iostream>  
#include <cstdlib>  
#include <getopt.h>  
  
int main(int argc, char* argv[]) {  
    int opt;  
    while ((opt = getopt(argc, argv, "a:b:c:")) != -1) {  
        switch (opt) {  
            case 'a':  
                std::cout << "option a with value '" << optarg << "'" << std::endl;  
                break;  
            case 'b':  
                std::cout << "option b with value '" << optarg << "'" << std::endl;  
                break;  
            case 'c':  
                std::cout << "option c with value '" << optarg << "'" << std::endl;  
                break;  
            default: /* '?' */  
                fprintf(stderr, "Usage: %s [-a arg] [-b arg] [-c arg]\n", argv[0]);  
                exit(EXIT_FAILURE);  
        }  
    }  
    return 0;  
}

在上面的代码中,getopt()函数接受三个参数:命令行参数的数量argc、命令行参数的值argv和一个字符串optstring,该字符串指定了程序所支持的选项。在这个例子中,使用-a、-b和-c来指定三个选项,并且每个选项都有一个相关的参数值。当getopt()函数解析到一个选项时,它会返回该选项的字符代码,并且将该选项的参数值存储在全局变量optarg中。然后,可以使用一个switch语句来检查返回的字符代码并执行相应的操作。

还可以使用getopt_long()函数来处理长选项,该函数接受一个额外的参数,该参数是一个指向option结构体的指针数组,其中每个结构体都包含一个长选项的名称和相关的参数信息。

含有可变形参的函数- 6.2.6 -

在C++中,可以使用可变形参的函数,也就是函数参数数量可变的函数。这种函数可以通过使用C++标准库中的std::tuple和std::variant来实现。

下面是一个使用std::tuple实现可变形参函数的例子:

#include <iostream>  
#include <tuple>  
  
void printValues(const std::tuple<int, float>& values) {  
    int intValue;  
    float floatValue;  
    std::tie(intValue, floatValue) = values;  // 使用 std::tie 解构元组  
    std::cout << "int: " << intValue << ", float: " << floatValue << std::endl;  
}  
  
int main() {  
    printValues({1, 2.0f});  // 输出:int: 1, float: 2  
    return 0;  
}

在上面的代码中,printValues()函数的参数是一个std::tuple<int, float>类型的元组,它可以接受两个参数。在函数内部,使用std::tie()函数将元组中的值解构到两个变量中,然后输出它们的值。在main()函数中,调用printValues()函数并传递两个参数,程序的输出结果是:int: 1, float: 2。

除了使用std::tuple,还可以使用std::variant来实现可变形参函数。下面是一个使用std::variant实现可变形参函数的例子:

#include <iostream>  
#include <variant>  
  
void printValue(const std::variant<int, float>& value) {  
    auto visitor = [](auto arg) {  
        using T = std::decay_t<decltype(arg)>;  
        std::cout << arg << " (" << typeid(T).name() << ")" << std::endl;  
    };  
    visit(visitor, value);  
}  
  
int main() {  
    printValue(1);  // 输出:1 (i)  
    printValue(2.0f);  // 输出:2 (f)  
    return 0;  
}

在上面的代码中,printValue()函数的参数是一个std::variant<int, float>类型的变体类型,它可以接受int或float类型的参数。在函数内部,定义了一个访问者(visitor),它可以根据参数的类型输出不同的结果。然后使用std::visit()函数将参数传递给访问者,并根据参数的类型执行不同的操作。在main()函数中,分别调用printValue()函数并传递int和float类型的参数,程序的输出结果是:1 (i)和2 (f)。