14

Google C++ 风格指南在输入参数(→ const ref, value)和输入输出或输出参数(→ 非 const 指针)之间做出了明确的区分(严格遵循cpplint.py):

C/C++ 函数的参数要么是函数的输入,要么是函数的输出,或者两者兼而有之。输入参数通常是值或常量引用,而输出和输入/输出参数将是非常量指针。

并进一步 :

事实上,在 Google 代码中,输入参数是值或 const 引用,而输出参数是指针,这是一个非常严格的约定。

但我无法弄清楚为什么输入/输出参数(我将输出参数放在一边)不应该通过引用传递。在stackoverflow上有很多与这个问题相关的主题:例如here,接受的答案清楚地表明

主要是关于风格

但如果

你希望能够传递空值,你必须使用一个指针

那么,如果我想避免指针为空,那么总是要求指针有什么意义呢?为什么只对输入参数使用引用?

4

4 回答 4

34

要求输出参数作为指针传递的原因很简单:

在调用站点清楚地表明该参数可能会发生突变:

foo(x, y);     // x and y won't be mutated
bar(x, &y);    // y may be mutated

当代码库发展并经历增量更改时,这些更改可能一直由可能不了解整个上下文的人进行审查,因此能够尽快了解更改的上下文和影响非常重要。因此,使用此样式规则,可以立即清楚更改是否会引入突变。

于 2014-10-18T16:04:44.373 回答
9

他们提出的观点(我不同意)是说我有一些功能

void foo(int a, Bar* b);

如果b参数是可选的,或者有时不需要,您可以像这样调用函数

foo(5, nullptr);

如果函数被声明为

void foo(int a, Bar& b);

那么就没有办法传入 a Bar

这一点(强调我的)完全基于意见,由开发人员自行决定。

事实上,在 Google 代码中,输入参数是值或 const 引用,而输出参数是指针,这是一个非常严格的约定。

如果我打算b成为一个输出参数,以下任何一个都是完全有效和合理的。

void foo(int a, Bar* b);  // The version Google suggests
void foo(int a, Bar& b);  // Reference version, also perfectly fine.
于 2014-10-18T15:17:11.880 回答
4

您是第一个问题:“那么,如果我想避免指针变为,那么总是null要求指针有什么意义?”

使用指针向调用者宣布他们的变量可能被修改。如果我打电话foo(bar)bar会被修改吗?如果我打电话foo(&bar),很明显 的值bar可能会被修改。
有许多函数示例采用null指示可选输出参数(我的头顶time就是一个很好的例子。)

您的第二个问题:“为什么只对输入参数使用引用?”

使用引用参数比使用指针参数更容易。

int foo(const int* input){
    int return = *input;

    while(*input < 100){
        return *= *input;
        (*input)++;
    }
}

使用参考重写的代码如下所示:

int foo(const int& input){
    int return = input;

    while(input < 100){
        return *= input;
        input++;
    }
}

您可以看到使用 aconst int& input简化了代码。

于 2014-10-18T15:52:01.500 回答
1

他们可能会使用它来保持一致性,因为他们使用输出参数作为对现有内存的引用(他们正在修改先前初始化的变量)和实际输出(假定输出参数由函数本身分配)。为了保持一致性,他们将其用作更清楚地指示输入与输出的一种方式。

如果您从不需要函数/方法来分配输出参数的内存,例如从查找返回指针或分配内存本身并通过指针返回,请使用引用。如果您需要这样做但不关心使用指针来指示参数是输入还是输出,请在适当的时候使用输出参数的引用。没有绝对要求在所有情况下都使用指针,除非该函数/方法本身的要求需要它。

于 2014-10-18T15:27:27.443 回答