C++ 指针与引用

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/114180/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-27 12:56:46  来源:igfitidea点击:

Pointer vs. Reference

c++variablespointersreference

提问by Hyman Reza

What would be better practice when giving a function the original variable to work with:

在为函数提供要使用的原始变量时,有什么更好的做法:

unsigned long x = 4;

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

or:

或者:

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

IOW: Is there any reason to pick one over another?

IOW:有什么理由选择一个?

回答by Nils Pipenbrinck

My rule of thumb is:

我的经验法则是:

Use pointers if you want to do pointer arithmetic with them (e.g. incrementing the pointer address to step through an array) or if you ever have to pass a NULL-pointer.

如果您想用指针进行指针运算(例如增加指针地址以遍历数组),或者您必须传递 NULL 指针,请使用指针。

Use references otherwise.

否则使用引用。

回答by Johann Gerell

I really think you will benefit from establishing the following function calling coding guidelines:

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

  1. As in all other places, always be const-correct.

    • Note: This means, among other things, that only out-values (see item 3) and values passed by value (see item 4) can lack the constspecifier.
  2. Only pass a value by pointer if the value 0/NULL is a valid input in the current context.

    • Rationale 1: As a caller, you see that whatever you pass in must bein a usable state.

    • Rationale 2: As called, you know that whatever comes in isin a usable state. Hence, no NULL-check or error handling needs to be done for that value.

    • Rationale 3: Rationales 1 and 2 will be compiler enforced. Always catch errors at compile time if you can.

  3. If a function argument is an out-value, then pass it by reference.

    • Rationale: We don't want to break item 2...
  4. Choose "pass by value" over "pass by const reference" only if the value is a POD (Plain old Datastructure) or small enough (memory-wise) or in other ways cheap enough (time-wise) to copy.

    • Rationale: Avoid unnecessary copies.
    • Note: small enoughand cheap enoughare not absolute measurables.
  1. 和所有其他地方一样,总是const正确的。

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

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

    • 理由2:由于,你知道,无论发生什么事的处于可用状态。因此,不需要对该值进行 NULL 检查或错误处理。

    • 基本原理 3:基本原理 1 和 2 将被编译器强制执行。如果可以,请始终在编译时捕获错误。

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

    • 理由:我们不想破坏第 2 项......
  4. 仅当值是 POD(普通旧数据结构)或足够小(内存方面)或以其他方式足够便宜(时间方面)进行复制时,才选择“按值传递”而不是“按常量引用传递” 。

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

回答by Aaron N. Tubbs

This ultimately ends up being subjective. The discussion thus far is useful, but I don't think there is a correct or decisive answer to this. A lot will depend on style guidelines and your needs at the time.

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

While there are some different capabilities (whether or not something can be NULL) with a pointer, the largest practical difference for an output parameter is purely syntax. Google's C++ Style Guide (https://google.github.io/styleguide/cppguide.html#Reference_Arguments), for example, mandates only pointers for output parameters, and allows only references that are const. The reasoning is one of readability: something with value syntax should not have pointer semantic meaning. I'm not suggesting that this is necessarily right or wrong, but I think the point here is that it's a matter of style, not of correctness.

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

回答by Max Caceres

You should pass a pointer if you are going to modify the value of the variable. Even though technically passing a reference or a pointer are the same, passing a pointer in your use case is more readable as it "advertises" the fact that the value will be changed by the function.

如果您要修改变量的值,您应该传递一个指针。尽管技术上传递引用或指针是相同的,但在您的用例中传递指针更具可读性,因为它“宣传”了值将被函数更改的事实。

回答by Kiley Hykawy

If you have a parameter where you may need to indicate the absence of a value, it's common practice to make the parameter a pointer value and pass in NULL.

如果您有一个参数,您可能需要在其中指示值的缺失,通常的做法是将该参数设为指针值并传入 NULL。

A better solution in most cases (from a safety perspective) is to use boost::optional. This allows you to pass in optional values by reference and also as a return value.

大多数情况下(从安全角度来看)更好的解决方案是使用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);
}

回答by RezaPlusPlus

Use a reference when you can, use a pointer when you have to. From C++ FAQ: "When should I use references, and when should I use pointers?"

尽可能使用引用,必要时使用指针。来自C++ FAQ:“什么时候应该使用引用,什么时候应该使用指针?”

回答by Saurabh Raoot

Pointers

指针

  • A pointer is a variable that holds a memory address.
  • A pointer declaration consists of a base type, an *, and the variable name.
  • A pointer can point to any number of variables in lifetime
  • A pointer that does not currently point to a valid memory location is given the value null (Which is zero)

    BaseType* ptrBaseType;
    BaseType objBaseType;
    ptrBaseType = &objBaseType;
    
  • The & is a unary operator that returns the memory address of its operand.

  • Dereferencing operator (*) is used to access the value stored in the variable which pointer points to.

       int nVar = 7;
       int* ptrVar = &nVar;
       int nVar2 = *ptrVar;
    
  • 指针是保存内存地址的变量。
  • 指针声明由基类型、* 和变量名组成。
  • 一个指针可以指向生命周期中任意数量的变量
  • 当前未指向有效内存位置的指针被赋予值 null(即为零)

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

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

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

Reference

参考

  • A reference (&) is like an alias to an existing variable.

  • A reference (&) is like a constant pointer that is automatically dereferenced.

  • It is usually used for function argument lists and function return values.

  • A reference must be initialized when it is created.

  • Once a reference is initialized to an object, it cannot be changed to refer to another object.

  • You cannot have NULL references.

  • A const reference can refer to a const int. It is done with a temporary variable with value of the 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
    
  • 引用 (&) 就像现有变量的别名。

  • 引用 (&) 就像一个自动取消引用的常量指针。

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

  • 创建引用时必须对其进行初始化。

  • 一旦一个引用被初始化为一个对象,它就不能被更改为引用另一个对象。

  • 您不能有 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

在此处输入图片说明

回答by Daniel Earwicker

Consider C#'s out keyword. The compiler requires the caller of a method to apply the out keyword to any out args, even though it knows already if they are. This is intended to enhance readability. Although with modern IDEs I'm inclined to think that this is a job for syntax (or semantic) highlighting.

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

回答by Daniel Earwicker

A reference is an implicit pointer. Basically you can change the value the reference points to but you can't change the reference to point to something else. So my 2 cents is that if you only want to change the value of a parameter pass it as a reference but if you need to change the parameter to point to a different object pass it using a pointer.

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

回答by NotJarvis

Pass by const reference unless there is a reason you wish to change/keep the contents you are passing in.

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

This will be the most efficient method in most cases.

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

Make sure you use const on each parameter you do not wish to change, as this not only protects you from doing something stupid in the function, it gives a good indication to other users what the function does to the passed in values. This includes making a pointer const when you only want to change whats pointed to...

确保在每个不想更改的参数上使用 const,因为这不仅可以防止您在函数中做一些愚蠢的事情,还可以很好地向其他用户指示该函数对传入的值做了什么。这包括在您只想更改指向的内容时制作一个指针 const...