指针与参考

时间:2008-09-22 10:38:32

标签: c++ variables pointers reference

在为函数提供原始变量时,最好的做法是:

unsigned long x = 4;

void func1(unsigned long& val) {
     val = 5;            
}
func1(x);

或:

void func2(unsigned long* val) {
     *val = 5;
}
func2(&x);

IOW:有没有理由选择一个而不是另一个?

12 个答案:

答案 0 :(得分:273)

我的经验法则是:

如果你想用它们进行指针运算(例如,递增指针地址以逐步执行数组),或者你必须传递NULL指针,请使用指针。

否则使用参考文献。

答案 1 :(得分:71)

我真的认为您将从建立以下函数调用编码指南中受益:

  1. 与所有其他地方一样,始终为const - 正确。

    • 注意:除其他外,这意味着只有out-values(参见第3项)和按值传递的值(参见第4项)可能缺少const说明符。
  2. 如果值0 / NULL是当前上下文中的有效输入,则仅通过指针传递值。

    • 基本原理1:作为来电者,您会看到中传递的任何内容必须处于可用状态。

    • 基本原理2:当调用时,您知道中的任何内容都是处于可用状态。因此,不需要对该值进行NULL检查或错误处理。

    • 原理3:基本原则1和2将编译器强制执行。如果可以的话,总是在编译时捕获错误。

  3. 如果函数参数是一个out-value,则通过引用传递它。

    • 理由:我们不想打破第2项......
  4. 只有当值为POD(Plain old Datastructure)或足够小(内存方式)或其他方式足够便宜时(时间 - ),选择“按值传递”而不是“通过const引用传递”明智的)复制。

    • 理由:避免不必要的副本。
    • 注意:足够小足够便宜不是绝对可衡量的。

答案 2 :(得分:24)

这最终会成为主观的。到目前为止的讨论很有用,但我认为没有正确或果断的答案。很大程度上取决于风格指南和当时的需求。

虽然使用指针有一些不同的功能(无论是否可以为NULL),但输出参数的最大实际差异纯粹是语法。例如,Google的C ++样式指南(https://google.github.io/styleguide/cppguide.html#Reference_Arguments)只强制指定输出参数,并且只允许使用const的引用。推理是可读性:具有值语法的东西不应该具有指针语义。我并不是说这必然是对或错,但我认为这是一个风格问题,而不是正确性。

答案 3 :(得分:7)

如果要修改变量的值,则应传递指针。 即使技术上传递引用或指针是相同的,在您的用例中传递指针也更具可读性,因为它“通告”该函数将更改该值的事实。

答案 4 :(得分:5)

如果你有一个参数,你可能需要指出缺少一个值,通常的做法是使参数成为指针值并传入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);
}

答案 5 :(得分:4)

尽可能使用引用,必要时使用指针。 来自C++ FAQ: "When should I use references, and when should I use pointers?"

答案 6 :(得分:4)

<强>指针

  • 指针是保存内存地址的变量。
  • 指针声明由基本类型,*和变量名称组成。
  • 指针可以指向生命周期中的任意数量的变量
  • 当前未指向有效内存位置的指针的值为null(为零)

    BaseType* ptrBaseType;
    BaseType objBaseType;
    ptrBaseType = &objBaseType;
    
  • &amp;是一元运算符,它返回其操作数的内存地址。

  • 解除引用运算符(*)用于访问存储在指针指向的变量中的值。

       int nVar = 7;
       int* ptrVar = &nVar;
       int nVar2 = *ptrVar;
    

<强>参考

  • 引用(&amp;)就像是现有变量的别名。

  • 引用(&amp;)就像一个自动解除引用的常量指针。

  • 它通常用于函数参数列表和函数返回值。

  • 创建参考时必须初始化。

  • 将引用初始化为对象后,无法将其更改为引用其他对象。

  • 您不能有NULL引用。

  • const引用可以引用const int。它由一个值为const

    的临时变量完成
    int i = 3;    //integer declaration
    int * pi = &i;    //pi points to the integer i
    int& ri = i;    //ri is refers to integer i – creation of reference and initialization
    

enter image description here

enter image description here

答案 7 :(得分:3)

引用是一个隐式指针。基本上,您可以更改引用指向的值,但不能将引用更改为指向其他内容。所以我的2美分是,如果您只想更改参数的值,请将其作为参考传递,但如果您需要将参数更改为指向另一个对象,请使用指针传递它。

答案 8 :(得分:3)

考虑C#的out关键字。编译器要求方法的调用者将out关键字应用于任何out args,即使它已经知道它们是否存在。这旨在增强可读性。虽然使用现代IDE,我倾向于认为这是语法(或语义)突出显示的工作。

答案 9 :(得分:2)

通过const引用,除非您有理由更改/保留您传入的内容。

在大多数情况下,这将是最有效的方法。

确保在每个不希望更改的参数上使用const,因为这不仅可以保护您不会在函数中做一些愚蠢的操作,而且可以很好地向其他用户表明函数对传入的值的作用。这包括当你只想改变指向...的什么时,制作指针const。

答案 10 :(得分:2)

指针:

  • 可以分配nullptr(或NULL)。
  • 在呼叫网站上,如果您的类型不是指针本身,则必须使用&, 明确地说你正在修改你的对象。
  • 指针可以反弹。

参考文献:

  • 不能为空。
  • 一旦绑定,就无法改变。
  • 来电者无需明确使用&。有时会考虑这一点 糟糕,因为你必须去执行该功能,看看是否 您的参数已被修改。

答案 11 :(得分:0)

引用类似于指针,除了您无需使用前缀∗来访问引用所引用的值。另外,初始化后不能引用该对象。

引用对于指定函数参数特别有用。

有关更多信息,请参见“ Bjarne Stroustrup”(2014年)第11-12页的“ C ++之旅”