指针与参考
给函数一个原始变量以供使用时,更好的做法是:
unsigned long x = 4; void func1(unsigned long& val) { val = 5; } func1(x);
或者:
void func2(unsigned long* val) { *val = 5; } func2(&x);
爱荷华州:有什么理由选择一个?
解决方案
我的经验法则是:
如果要使用指针进行算术运算(例如,增加指针地址以遍历数组)或者必须传递NULL指针,请使用指针。
否则使用引用。
我真的认为我们将从建立以下函数调用编码准则中受益:
- 基本原理2:正如我们所说的,我们知道进入的一切都处于可用状态。因此,不需要对该值进行NULL检查或者错误处理。
- 基本原理3:基本原理1和2将由编译器强制执行。如果可以,请始终在编译时捕获错误。
- 注意:足够小和足够便宜并不是绝对的衡量指标。
通过const引用传递,除非我们出于某种原因希望更改/保留要传递的内容。
在大多数情况下,这将是最有效的方法。
确保在不希望更改的每个参数上使用const,因为这不仅可以保护我们避免在函数中做一些愚蠢的事情,而且还可以向其他用户很好地指示函数对传入值的作用。这包括当我们只想更改指向的内容时使指针为const。
这最终最终成为主观的。到目前为止的讨论是有用的,但我认为对此没有正确或者决定性的答案。很大程度上取决于样式准则和我们当时的需求。
尽管指针具有一些不同的功能(某些东西是否可以为NULL),但输出参数的最大实际差异是语法。例如,Google的C ++样式指南(https://google.github.io/styleguide/cppguide.html#Reference_Arguments)仅规定输出参数的指针,并且仅允许const引用。推理是可读性之一:具有值语法的内容不应具有指针语义。我并不是说这必然是对还是错,但是我认为这里的重点是样式问题,而不是正确性。
引用是隐式指针。基本上,我们可以更改参考指向的值,但不能更改参考以指向其他值。所以我的2美分是,如果我们只想更改参数的值,请将其作为引用传递,但是如果我们需要更改参数以指向其他对象,则使用指针将其传递。
如果要修改变量的值,则应传递一个指针。
即使从技术上讲传递引用或者指针在技术上是相同的,但在用例中传递指针更易读,因为它"宣告"值将由函数更改的事实。
如果我们有一个可能需要指示不存在值的参数,通常的做法是使该参数成为指针值并传入NULL。
在大多数情况下(从安全角度而言),更好的解决方案是使用boost :: optional。这使我们可以通过引用以及作为返回值来传递可选值。
// Sample method using optional as input parameter void PrintOptional(const boost::optional<std::string>& optional_str) { if (optional_str) { cout << *optional_str << std::endl; } else { cout << "(no string)" << std::endl; } } // Sample method using optional as return value boost::optional<int> ReturnOptional(bool return_nothing) { if (return_nothing) { return boost::optional<int>(); } return boost::optional<int>(42); }
考虑一下C#的out关键字。编译器要求方法的调用者将out关键字应用于任何out args,即使它已经知道它们是否存在也是如此。这是为了增强可读性。尽管对于现代IDE,我倾向于认为这是语法(或者语义)突出显示的工作。