C++ 指向引用的指针和指向指针的引用之间的区别

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1898524/
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 21:31:35  来源:igfitidea点击:

Difference between pointer to a reference and reference to a pointer

c++memorypointersreference

提问by AraK

What is the difference between pointer to a reference, reference to a pointer and pointer to a pointer in C++?

C ++中指向引用的指针,指向指针的引用和指向指针的指针之间有什么区别?

Where should one be preferred over the other?

哪里应该优先于另一个?

回答by AraK

First, a reference to a pointer is like a reference to any other variable:

首先,对指针的引用就像对任何其他变量的引用:

void fun(int*& ref_to_ptr)
{
    ref_to_ptr = 0; // set the "passed" pointer to 0
    // if the pointer is not passed by ref,
    // then only the copy(parameter) you received is set to 0,
    // but the original pointer(outside the function) is not affected.
}

A pointer to reference is illegal in C++, because -unlike a pointer- a reference is just a concept that allows the programmer to make aliasesof something else. A pointer is a place in memorythat has the address of something else, but a reference is NOT.

指向引用的指针在 C++ 中是非法的,因为 - 与指针不同 - 引用只是一个允许程序员为其他事物创建别名的概念。指针是内存中具有其他地址的位置,但引用不是。

Now the last point might not be crystal clear, if you insist on dealing with references as pointers. e.g.:

如果您坚持将引用作为指针处理,那么最后一点可能不是很清楚。例如:

int x;
int& rx = x; // from now on, rx is just like x.
// Unlike pointers, refs are not real objects in memory.
int* p = &x; // Ok
int* pr = ℞ // OK! but remember that rx is just x!
// i.e. rx is not something that exists alone, it has to refer to something else.
if( p == pr ) // true!
{ ... }

As you can see from the above code, when we use the reference, we are not dealing with something separated from what it refers to. So, the address of a reference is just the address of what it refers to. Thats why there is no such thing called the address of the reference in terms of what youare talking about.

从上面的代码可以看出,当我们使用引用时,我们并没有处理与其所引用的内容分开的东西。所以,引用的地址就是它所引用的地址。这就是为什么就所谈论的内容而言,没有所谓的参考地址这样的东西。

回答by LeopardSkinPillBoxHat

Pointer to a pointer

指向指针的指针

A pointerin C++ is just a value which stores a memory location (generally as a 32-bit value).

C++ 中的指针只是一个存储内存位置的值(通常为 32 位值)。

Let's say you had an user input integer value (78== 0x4Ein hex).

假设您有一个用户输入的整数值(十六进制中的78== 0x4E)。

It would be stored in memory in a similar way to this (I'm purposely simplifying things for this example):

它将以与此类似的方式存储在内存中(我特意为这个例子简化了一些事情):

Memory address    Value
0x12345678        0x0000004E

If you wanted to create a "pointer" to this value, it would look like this in memory:

如果你想创建一个指向这个值的“指针”,它在内存中看起来像这样:

Memory address    Value
0x22334455        0x12345678

At memory address 0x22334455you now have a "pointer" whose value is 0x12345678, or the memory address of where the user input integer value (0x4E) is stored.

在内存地址处,0x22334455您现在有一个“指针”,其值为0x12345678,或存储用户输入整数值 ( 0x4E)的内存地址。

Let's say you wanted to create a "pointer" to this pointer value. It would look like this:

假设您想创建一个指向该指针值的“指针”。它看起来像这样:

Memory address    Value
0x11335577        0x22334455

You now have a new "pointer" value in memory which is storing the memory address of the previously-defined pointer value.

您现在在内存中有一个新的“指针”值,用于存储先前定义的指针值的内存地址。

Pointers can be created like this indefinitely - the key is remembering that a pointer is just another value that the compiler interprets as a memory location (and it provides various access semantics such as *and ->which are special to "pointer" types).

指针可以像这样无限期地创建 - 关键是要记住,指针只是编译器解释为内存位置的另一个值(并且它提供了各种访问语义,例如“指针”类型特有的*->)。

Reference to a pointer

对指针的引用

A referencecan be thought of as a view, or alias, on to another real object. When you create a reference to a pointer called myReference, you are simply defining a new name called myReferencewhich can be used to access the pointer which you have previous defined in memory.

参考可以被认为是一个视图,或别名,到另一个真实对象。当您创建对名为 的指针的引用时myReference,您只需定义一个名为 的新名称myReference,该名称可用于访问您之前在内存中定义的指针。

Internally, references are implemented using pointers, but this is beyond the scope of your question.

在内部,引用是使用指针实现的,但这超出了您的问题范围。

References have restrictions over other types in C++ - for example, you mustalways initialize a reference to "refer" to a real object when you create it, while a pointer maypoint to memory which is invalid, or uninitialised.

引用对 C++ 中的其他类型有限制 - 例如,您必须始终在创建引用时初始化对“引用”真实对象的引用,而指针可能指向无效或未初始化的内存。

Pointer to a reference

指向引用的指针

This doesn't exist. As stated earlier, a reference is merely an alias to another object. You can't "point" to a reference, because it isn't an object in itself but merely another name for a real object.

这不存在。如前所述,引用只是另一个对象的别名。你不能“指向”一个引用,因为它本身并不是一个对象,而只是一个真实对象的另一个名字。

Of course, you can have a pointer to the object that a reference is referring to. But now we are back in vanilla pointer territory.

当然,您可以拥有一个指向引用所指对象的指针。但现在我们又回到了原版指针领域。

Note about parameters

参数说明

When you pass a parameter by valueto a method or routine, you are essentially passing a "copy" of the object to the method. Any changes you make to the value within the routine will be lost when the routine returns, because the parameter will be treated as a local variable in the context of the routine.

当您按值将参数传递给方法或例程时,您实际上是将对象的“副本”传递给方法。当例程返回时,您对例程中的值所做的任何更改都将丢失,因为参数将被视为例程上下文中的局部变量。

If you want to modify a parameter which is passed in so the client (calling) code can access the change, you must pass the parameter by pointeror by reference.

如果要修改传入的参数以便客户端(调用)代码可以访问更改,则必须通过指针引用传递参数。

For example:

例如:

void myMethod(int myValue)
{
    // NOTE: This change will be lost to the caller!
    myValue = 5;
}

void myMethod2(int* myValue)
{
    // Correct way of modifying pointer parameter value
    *myValue = 5;
}

void myMethod3(int& myValue)
{
    // Correct way of modifying reference parameter value
    myValue = 5;
}

Let's now say that your method wants to allocate memory for a pointer. You could be tempted to do this:

现在假设您的方法想要为指针分配内存。你可能会想这样做:

void myMethod4(int* myValue)
{
    // Warning: You will lose the address of the allocated
    // memory when you return!
    myValue = new int[5];
}

But remember, you are modifying the copyof the pointer value here, not the realpointer value. Since you are wanting to modify the pointerin this routine, and not the valuethat the pointer "points" to, you need to pass it in as a "pointer to a pointer" or a "reference to a pointer":

但请记住,您在这里修改的是指针值的副本,而不是真正的指针值。由于您要修改此例程中的指针,而不是指针“指向”的,因此您需要将其作为“指向指针的指针”或“对指针的引用”传递:

void myMethod5(int** myValue)
{
    // Correct way of allocating memory in a method
    // via pointer-to-pointer
    *myValue = new int[5];
}

void myMethod6(int*& myValue)
{
    // Correct way of allocating memory in a method
    // via reference-to-pointer
    myValue = new int[5];
}

In these bottom 2 examples, the code which is calling myMethod5and myMethod6will correctly get the memory address of the newly-allocated memory via the myValueparameter pointer or reference.

在这些底2个的例子中,代码被调用myMethod5myMethod6通过将正确地得到新分配的存储器的存储器地址myValue的参数的指针或引用。

回答by Fred

There is no such thing as a pointer to a reference.

没有指向引用的指针这样的东西。

回答by McPherrinM

A reference is an abstraction away from pointers. References are a bit harder to screw up, especially for novices, and are a bit more high level.

引用是远离指针的抽象。参考文献有点难搞定,尤其是对于新手来说,而且水平高一点。

You don't needreferences. You can always use pointers. However, sometimes code can be easier to read with them.

不需要参考。你总是可以使用指针。但是,有时使用它们可以更容易地阅读代码。

A typical beginner example is a linked list. Imagine you have a variable called "list" that contains a pointer to the first one. If you wanted to add something to the head, you'd need to give your add() a double pointer, since it needs to be able to modify "head". However, you can use a reference to a pointer instead. Here, we want to use pointers in the list itself since we'll be mutating them, but the add() function will be clearer if we pass in a reference to the head of the list instead of a double pointer.

一个典型的初学者示例是链表。假设您有一个名为“list”的变量,其中包含指向第一个变量的指针。如果你想向头部添加一些东西,你需要给你的 add() 一个双指针,因为它需要能够修改“头部”。但是,您可以改用对指针的引用。在这里,我们想在列表本身中使用指针,因为我们将改变它们,但是如果我们传递对列表头部的引用而不是双指针,那么 add() 函数会更清晰。

They're simply a style choice. If you're working on a larger project, you should go with the style of the project. If not, you can use whatever you feel is preferable. You should, however, be comfortable using all styles if you even hope to be a mildly successful C++ programmer.

它们只是一种风格选择。如果你正在处理一个更大的项目,你应该采用项目的风格。如果没有,您可以使用您认为更可取的任何内容。但是,如果您甚至希望成为一名稍微成功的 C++ 程序员,那么您应该习惯于使用所有样式。

It is also worthwhile that you can't have a pointer to a reference. This is because references are really just another name for another variable, which may be in some other scope. Having a pointer to a reference doesn't make sense. What you'd really want is just a pointer to whatever the original data was, no references involved.

同样值得的是,您不能拥有指向引用的指针。这是因为引用实际上只是另一个变量的另一个名称,它可能在其他范围内。拥有指向引用的指针没有意义。您真正想要的只是一个指向原始数据的指针,不涉及引用。

回答by Ben Voigt

It is important to note that although a reference is not an object and therefore does not have an accessible address, a reference can be contained within an object and the containing object does have an address.

需要注意的是,虽然引用不是对象,因此没有可访问的地址,但引用可以包含在对象中,并且包含对象确实有地址。

struct contains_ref
{
     int& ref;
     contains_ref(int& target) : ref(target) {}
};

The "reference is an alias" explanation is not incorrect, but is often accompanied by misleading claims. A reference is not equivalent to the original object. It has its own lifetime, determined by the scope or object that contains it, and not the object it refers to. And a reference can outlive an object and be used to refer to a new object created at the same address.

“引用是别名”的解释并没有错,但往往伴随着误导性的声明。引用不等同于原始对象。它有自己的生命周期,由包含它的范围或对象决定,而不是它所引用的对象。并且一个引用可以比一个对象存活时间更长,并且可以用来引用在同一地址创建的新对象。

Treat a reference as what it really is -- an abstraction around a pointer that excludes null as a valid value, and prevents reseating1-- and not something magic. The only unusual property of a reference that isn't derived from its pointer nature is lifetime extension of temporaries.

将引用视为它的真正含义——指针周围的抽象,将 null 作为有效值排除在外,并防止重新设置1——而不是魔法。引用的唯一不从其指针性质派生的不寻常属性是临时对象的生命周期扩展。



1Actually this is a consequence of the fact that C++ doesn't provide any syntax for referring to the reference itself rather than its target. All operators, including the assignment operator, are simply applied to the target.

1实际上,这是因为 C++ 不提供任何语法来引用引用本身而不是其目标。所有运算符,包括赋值运算符,都简单地应用于目标。

回答by Escualo

Just try and see for yourself what is each thing holding. The sample program simply prints the value for an int and the addresses of different entities:

试着亲自看看每件东西都有什么。示例程序只是打印一个 int 的值和不同实体的地址:

#include<stdio.h>

int main(){
  int myInt ;
  int *ptr_to_myInt = &myInt;
  int *ptr_to_myInt_ref = ptr_to_myInt;

  myInt = 42;

  printf("myInt is %d\n",myInt);
  printf("ptr_to_myInt is %x\n",ptr_to_myInt);
  printf("ptr_to_myInt_ref is %x\n",ptr_to_myInt_ref);
  printf("&ptr_to_myInt is %x\n",&ptr_to_myInt);

  return 0;
}

Output:

输出:

myInt is 42
ptr_to_myInt is bffff858
ptr_to_myInt_ref is bffff858
&ptr_to_myInt is bffff854

So, the pointer to the int and the pointer to the reference of the int are exactly the same thing. This is obvious from the code, because the pointer to a reference is simply another way of aliasing a pointer (it is saying "hold the following address for me").

因此,指向 int 的指针和指向 int 引用的指针完全相同。这从代码中很明显,因为指向引用的指针只是为指针设置别名的另一种方式(它是说“为我保留以下地址”)。

Now, the pointer also needs some space in memory, and if you print the reference to this pointer (the last printf statement) it simply indicates the place in memory where the pointer resides.

现在,指针还需要内存中的一些空间,如果您打印对此指针的引用(最后一个 printf 语句),它只是指示指针所在的内存位置。