C++ 返回指针/引用

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

C++ Returning Pointers/References

c++pointersreturn

提问by Tyler McHenry

I have a fairly good understanding of the dereferencing operator, the address of operator, and pointers in general.

我对解引用运算符、运算符地址和一般指针有相当好的理解。

I however get confused when I see stuff such as this:

然而,当我看到这样的东西时,我会感到困惑:

int* returnA() {
    int *j = &a;
    return j;
}

int* returnB() {
    return &b;
}

int& returnC() {
    return c;
}

int& returnC2() {
    int *d = &c;
    return *d;
}
  1. In returnA()I'm asking to return a pointer; just to clarify this works because jis a pointer?
  2. In returnB()I'm asking to return a pointer; since a pointer points to an address, the reason why returnB()works is because I'm returning &b?
  3. In returnC()I'm asking for an address of intto be returned. When I return cis the &operator automatically "appended" c?
  4. In returnC2()I'm asking again for an address of intto be returned. Does *dwork because pointers point to an address?
  1. returnA()我要求返回一个指针;只是为了澄清这一点,因为它j是一个指针?
  2. returnB()我要求返回一个指针;因为一个指针指向一个地址,所以returnB()工作的原因是因为我正在返回&b
  3. returnC()我要求int返回的地址。当我返回时c&操作员会自动“附加”c吗?
  4. returnC2()我再次要求int返回的地址。是否*d工作,因为指针指向的地址?

Assume a, b, c are initialized as integers as Global.

假设 a、b、c 被初始化为整数作为 Global。

Can someone validate if I am correct with all four of my questions?

有人可以验证我的所有四个问题是否正确吗?

采纳答案by Péter T?r?k

In returnA() I'm asking to return a pointer; just to clarify this works because j is a pointer?

在 returnA() 我要求返回一个指针;只是为了澄清这是有效的,因为 j 是一个指针?

Yes, int *j = &ainitializes jto point to a. Then you return the value of j, that is the address of a.

是的,int *j = &a初始化j为指向a。然后返回 的值j,即 的地址a

In returnB() I'm asking to return a pointer; since a pointer points to an address, the reason why returnB() works is because I'm returning &b?

在 returnB() 我要求返回一个指针;因为一个指针指向一个地址,所以 returnB() 工作的原因是因为我正在返回 &b?

Yes. Here the same thing happens as above, just in a single step. &bgives the address of b.

是的。这里发生了与上面相同的事情,只需一步。&b给出 的地址b

In returnC() I'm asking for an address of int to be returned. When I return c is the & operator automatically appended?

在 returnC() 中,我要求返回 int 的地址。当我返回 c 时, & 运算符会自动附加吗?

No, it is a reference to an int which is returned. A reference is not an address the same way as a pointer is - it is just an alternative name for a variable. Therefore you don't need to apply the &operator to get a reference of a variable.

不,它是对返回的 int 的引用。引用不像指针那样是地址——它只是变量的替代名称。因此,您不需要应用&运算符来获取变量的引用。

In returnC2() I'm asking again for an address of int to be returned. Does *d work because pointers point to an address?

在 returnC2() 中,我再次要求返回 int 的地址。*d 是否工作,因为指针指向地址?

Again, it is a reference to an int which is returned. *drefers to the original variable c(whatever that may be), pointed to by c. And this can implicitly be turned into a reference, just as in returnC.

同样,它是对返回的 int 的引用。*d指的是cc.指向的原始变量(无论是什么)。这可以隐式地转换为引用,就像在returnC.

Pointers do not in general point to an address (although they can - e.g. int**is a pointer to pointer to int). Pointers arean address of something. When you declare the pointer like something*, that somethingis the thing your pointer points to. So in my above example, int**declares a pointer to an int*, which happens to be a pointer itself.

指针通常不指向地址(尽管它们可以 - 例如int**是指向 int 的指针的指针)。指针某物的地址。当您像 一样声明指针时something*,这something就是您的指针指向的对象。所以在我上面的例子中,int**声明了一个指向 an 的指针int*,它恰好是一个指针本身。

回答by Tyler McHenry

Although Peter answered your question, one thing that's clearly confusing you is the symbols *and &. The tough part about getting your head around these is that they both have two different meanings that have to do with indirection (even excluding the third meanings of *for multiplication and &for bitwise-and).

尽管彼得回答了您的问题,但显然让您感到困惑的一件事是符号*&。解决这些问题的困难之处在于它们都有两种不同的含义,与间接相关(甚至不包括*乘法和&按位与的第三种含义)。

  • *, when used as part of a typeindicates that the type is a pointer: intis a type, so int*is a pointer-to-int type, and int**is a pointer-to-pointer-to-int type.

  • &when used as part of a typeindicates that the type is a reference. intis a type, so int&is a reference-to-int (there is no such thing as reference-to-reference). References and pointers are used for similar things, but they are quite different and not interchangable. A reference is best thought of as an alias, or alternate name, for an existing variable. If xis an int, then you can simply assign int& y = xto create a new name yfor x. Afterwords, xand ycan be used interchangeably to refer to the same integer. The two main implications of this are that references cannot be NULL (since there must be an original variable to reference), and that you don't need to use any special operator to get at the original value (because it's just an alternate name, not a pointer). References can also not be reassigned.

  • *when used as a unary operatorperforms an operation called dereference(which has nothing to do with reference types!). This operation is only meaningful on pointers. When you dereference a pointer, you get back what it points to. So, if pis a pointer-to-int, *pis the intbeing pointed to.

  • &when used as a unary operatorperforms an operation called address-of. That's pretty self-explanatory; if xis a variable, then &xis the address of x. The address of a variable can be assigned to a pointer to the type of that variable. So, if xis an int, then &xcan be assigned to a pointer of type int*, and that pointer will point to x. E.g. if you assign int* p = &x, then *pcan be used to retrieve the value of x.

  • *, 当用作类型的一部分时 表示该类型是指针: int是类型,因此int*是指向 int 类型int**的指针,并且是指向int 类型的指针。

  • &当用作类型的一部分时,表示该类型是一个引用。int是一种类型,int&对 int 的引用也是一种类型(没有引用对引用这样的东西)。引用和指针用于类似的事情,但它们完全不同且不可互换。最好将引用视为现有变量的别名或备用名称。如果xint,那么你可以简单地分配int& y = x到创建一个新的名称yx。后记xy可以互换使用,指代同一个整数。这样做的两个主要含义是引用不能为 NULL(因为必须有一个原始变量来引用),并且您不需要使用任何特殊运算符来获取原始值(因为它只是一个备用名称,不是指针)。引用也不能重新分配。

  • *当用作一元运算符时,执行称为取消引用的操作(与引用类型无关!)。这个操作只对指针有意义。当你取消引用一个指针时,你会得到它所指向的东西。所以,如果p是一个指针到INT,*pint被指向。

  • &当用作一元运算符时,执行称为address-of的操作。这是不言自明的。如果x是变量,则&x是 的地址x。可以将变量的地址分配给指向该变量类型的指针。因此,如果xint,则&x可以分配给类型为 的指针int*,该指针将指向x。例如,如果您赋值int* p = &x*p则可用于检索 的值x

So remember, the type suffix &is for references, and has nothing to do with the unary operatory &, which has to do with getting addresses for use with pointers. The two uses are completely unrelated. And *as a type suffix declares a pointer, while *as a unary operator performs an action on pointers.

所以请记住,类型后缀&是用于引用的,与一元运算符无关&,它与获取用于指针的地址有关。这两种用途完全无关。并且*作为类型后缀声明一个指针,而*作为一元运算符对指针执行操作。

回答by Berhe Abrha

Tyler, that was very helpful explanation, I did some experiment using visual studio debugger to clarify this difference even further:-

泰勒,这是非常有用的解释,我使用 Visual Studio 调试器做了一些实验,以进一步阐明这种差异:-

int sample = 90;
int& alias = sample;
int* pointerToSample  = &sample;

Name                  Address                        Type
&alias                0x0112fc1c {90}                int *
&sample               0x0112fc1c {90}                int *
pointerToSample       0x0112fc1c {90}                int *
*pointerToSample    90                       int
alias   90                                       int &
&pointerToSample      0x0112fc04 {0x0112fc1c {90}}   int * *

Memory Layout

内存布局

PointerToSample       Sample/alias
_______________......____________________
0x0112fc1c |          |   90   |
___________|___.....__|________|_______...

[0x0112fc04]  ...      [0x0112fc1c

回答by Martin York

In returnC() and returnC2() you are not asking to return the address.

在 returnC() 和 returnC2() 中,您不要求返回地址。

Both these functions return references to objects.
A reference is not the address of anything it is an alternative name of something (this may mean the compiler may (or may not depending on situation) use an address to represent the object (alternatively it may also know to keep it in register)).

这两个函数都返回对对象的引用。
引用不是任何事物的地址,它是事物的替代名称(这可能意味着编译器可能(或可能不取决于情况)使用地址来表示对象(或者它也可能知道将其保留在寄存器中)) .

All you know that a reference points at a specific object.
While a reference itself is not an object just an alternative name.

所有你知道的,一个参考点指向一个特定的对象。
虽然引用本身不是一个对象,但它只是一个替代名称。

回答by Thomas Matthews

All of your examples produce undefined run-time behavior. You are returning pointers or references to items that disappear after execution leaves the function.

您的所有示例都会产生未定义的运行时行为。您正在返回对在执行离开函数后消失的项目的指针或引用。

Let me clarify:

让我澄清一下:

int * returnA()
{
  static int a;  // The static keyword keeps the variable from disappearing. 
  int * j = 0;   // Declare a pointer to an int and initialize to location 0.
  j = &a;        // j now points to a.
  return j;      // return the location of the static variable (evil).
}

In your function, the variable jis assigned to point to a's temporary location. Upon exit of your function the variable adisappears, but it's former location is returned via j. Since ano longer exists at the location pointed to by j, undefined behavior will happen with accessing *j.

在您的函数中,变量j被分配为指向a的临时位置。退出函数后,变量a消失,但它以前的位置通过j. 由于a在 指向的位置不再存在j,访问 时会发生未定义的行为*j

Variables inside functions should not be modified via reference or pointer by other code. It can happen although it produces undefined behavior.

其他代码不应通过引用或指针修改函数内的变量。尽管它会产生未定义的行为,但它可能会发生。

Being pedantic, the pointers returned should be declared as pointing to constant data. The references returned should be const:

迂腐,返回的指针应该声明为指向常量数据。返回的引用应该是 const:

const char * Hello()
{
  static const char text[] = "Hello";
  return text;
}

The above function returns a pointer to constant data. Other code can access (read) the static data but cannot be modified.

上面的函数返回一个指向常量数据的指针。其他代码可以访问(读取)静态数据但不能修改。

const unsigned int& Counter()
{
  static unsigned int value = 0;
  value = value + 1;
  return value;
}

In the above function, the valueis initialized to zero on the first entry. All next executions of this function cause valueto be incremented by one. The function returns a reference to a constant value. This means that other functions can use the value (from afar) as if it was a variable (without having to dereference a pointer).

在上面的函数中,value在第一个条目上初始化为零。此函数的所有下一次执行value都会加一。该函数返回对常量值的引用。这意味着其他函数可以(从远处)使用该值,就好像它是一个变量一样(而不必取消对指针的引用)。

In my thinking, a pointer is used for an optional parameter or object. A reference is passed when the object must exist. Inside the function, a referenced parameter means that the value exists, however a pointer must be checked for null before dereferencing it. Also, with a reference, there is more guarantee that the target object is valid. A pointer could point to an invalid address (not null) and cause undefined behavior.

在我看来,指针用于可选参数或对象。当对象必须存在时传递引用。在函数内部,被引用的参数意味着该值存在,但是在取消引用之前必须检查指针是否为空。此外,通过引用,可以更好地保证目标对象是有效的。指针可能指向无效地址(非空)并导致未定义的行为。

回答by Puppy

Semantically, references do act as addresses. However, syntactically, they are the compiler's job, not yours, and you can treat a reference as if it is the original object it points to, including binding other references to it and having them refer to the original object too. Say goodbye to pointer arithmetic in this case.

从语义上讲,引用确实充当地址。但是,在语法上,它们是编译器的工作,而不是您的工作,您可以将引用视为它指向的原始对象,包括将其他引用绑定到它并使它们也引用原始对象。在这种情况下告别指针算法。

The downside of that is that you can't modify what they refer to - they are bound at construct time.

这样做的缺点是你不能修改它们所指的东西——它们在构造时被绑定。