指针与参考

时间:2020-03-06 14:32:00  来源:igfitidea点击:

给函数一个原始变量以供使用时,更好的做法是:

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,我倾向于认为这是语法(或者语义)突出显示的工作。