int foo(type& bar); 是一种不好的编程实践吗?

3

好的,我们现在来到了一个与IT技术有关的翻译任务。需要翻译的内容是:“嗯,我们又来到了一个我C++书籍中提到的实践问题。它说“返回值(非void)函数不应该将引用类型作为参数。”所以基本上如果你想实现这样一个函数:”

int read_file(int& into){
   ...
}

如果一个函数将整数返回值用作某种错误指示器(忽略了我们有异常的事实),那么这个函数就写得很糟糕,实际上应该像这样:
void read_file(int& into, int& error){

}

对我而言,第一个选项更加清晰易用。如果你想忽略错误值,可以轻松地这样做。但是这本书建议使用后者。请注意,这本书并没有说返回值函数不好。它更倾向于说你应该只返回一个值或者只使用引用。

你对此有什么想法?我的书写得很烂吗?(再次)


可能是 https://dev59.com/FHE85IYBdhLWcg3wx2n2 的重复问题。 - Billy ONeal
1
@Brian 我不是在谈论异常,这本书也没有涉及到异常。假设由于某种原因,在您的下一个C ++项目中无法使用异常。按照这种方式进行操作是否是不良实践? - Earlz
@Billy 类似,但书籍尚未涉及对象或任何其他内容。所以我们正在谈论简单类型。 - Earlz
@Pindat 噢,糟糕。我知道有点不同。忘记格式化代码了。 - Earlz
我认为我的问题与此相关:https://dev59.com/RnRC5IYBdhLWcg3wXPwC - Fred Larson
在某个时候,你会到达关于 HRESULTS 的章节,一切都会豁然开朗。 - wqw
5个回答

10

这个建议有些愚蠢。直接返回值会更小,更容易输入。

直接返回:

if (read_file(...)) {
    ... handle problem ...
}

间接返回:

int status;

read_file(..., status);
if (status) {
    ... handle problem ...
}

编辑:更大的问题是是否根本要使用非const引用参数。参数产生副作用可能会令人惊讶。一个编码标准指出,参考参数应该是const,输出参数应该使用指针。这样读者在调用时就能看到&并发出“这个参数会被修改”的警告。


关于非const位,是的我已经思考了很多。我写的大部分都是C而不是C ++,所以我通常使用指针而不是引用。 - Earlz
1
@Brian Neal:这就是重点。代码应该力求在阅读调用站点时就能够相当容易地理解。通过清晰地标识(通常是)罕见的输出参数,您可以减轻读者不得不不断参考签名的负担。(他们无论如何都会做得很糟糕,从而产生可避免的错误。) - Daniel Newby
1
我认为在C++中,你需要通过先阅读函数的签名和头文件中的任何注释来理解函数,而不是依赖于调用方。毕竟,引用被发明是因为它们解决了指针无法解决的问题。你不可能总是把所有的输出参数都作为指针。 - Brian Neal
1
@aperkins - 引用主要是为了支持运算符重载而创建的。指针会带来一些额外的问题,因为它们可以为空。如果我想告诉调用者不能传入空值,我会使用引用。因此,那些规定“所有输出或输入输出参数必须是指针”的编码标准对我来说似乎没有增加任何价值。仅代表个人观点。 - Brian Neal
1
@aperkins 当然可以,但是就像我说的那样,我不认为这是最佳实践。我很少见到在实际开发中或者STL和其他常用库中使用这种方法。 - Brian Neal
显示剩余3条评论

5
我��为在一个项目中保持一致性比宣传某种方式更好的重要。

+1 - 异常使用过程中最糟糕的问题来自于将使用它们的代码与不知道它们的代码混合。对于这个问题,如果你习惯了代码库中的第二种风格,那么很容易意外忽略一个使用第一种风格的孤立函数返回的错误。如果您习惯使用第一种风格,则使用第二种风格的孤立函数会显得尴尬。Win32、标准库和POSIX通常使用第一种风格,因此这可能是您决策的影响因素。 - Eclipse

3

这是一个相当无聊且主观的风格辩论。个人而言,我更喜欢返回std::pair,一个结构体或者(在TR1中)一个元组。


1

他们试图教你实践“如果你返回一个值,请不要修改调用参数中的变量”。

相反,你可以像下面这样做:

int read_file(const int& into){ ... }

我的语法可能有些不对,但 const 告诉它你不能在方法内部更改它,但你仍然可以通过引用传递,这对于对象来说非常好。 对于 int 而言,它并没有真正带给你任何东西。


编辑:另外,正如其他人所指出的那样,如果您的目标是具有多个返回值,则通常最好遵循书中建议的方法,或者创建一个“组合”返回类型 - 使用一对,自定义类型等。

0
//somewhere deep in the code space
a = func(i); //i is modified inside func() or not?    
j = i; //what is this for? depends on the answer to the first question

如果代码是根据书上建议的规则编写的,通过查看调用站点,您可以确定“i”未被修改,因此代码比其他情况下更能传达信息给您

无论如何,我更喜欢返回一个元组,而不是通过引用进行修改


是的,以我的观点来看,非常量引用是有害的。 - Earlz

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接