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
C++ Returning Pointers/References
提问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;
}
- In
returnA()
I'm asking to return a pointer; just to clarify this works becausej
is a pointer? - In
returnB()
I'm asking to return a pointer; since a pointer points to an address, the reason whyreturnB()
works is because I'm returning&b
? - In
returnC()
I'm asking for an address ofint
to be returned. When I returnc
is the&
operator automatically "appended"c
? - In
returnC2()
I'm asking again for an address ofint
to be returned. Does*d
work because pointers point to an address?
- 在
returnA()
我要求返回一个指针;只是为了澄清这一点,因为它j
是一个指针? - 在
returnB()
我要求返回一个指针;因为一个指针指向一个地址,所以returnB()
工作的原因是因为我正在返回&b
? - 在
returnC()
我要求int
返回的地址。当我返回时c
,&
操作员会自动“附加”c
吗? - 在
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 = &a
initializes j
to 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. &b
gives 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. *d
refers 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
指的是c
由c
.指向的原始变量(无论是什么)。这可以隐式地转换为引用,就像在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 something
is 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:int
is a type, soint*
is a pointer-to-int type, andint**
is a pointer-to-pointer-to-int type.&
when used as part of a typeindicates that the type is a reference.int
is a type, soint&
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. Ifx
is anint
, then you can simply assignint& y = x
to create a new namey
forx
. Afterwords,x
andy
can 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, ifp
is a pointer-to-int,*p
is theint
being pointed to.&
when used as a unary operatorperforms an operation called address-of. That's pretty self-explanatory; ifx
is a variable, then&x
is the address ofx
. The address of a variable can be assigned to a pointer to the type of that variable. So, ifx
is anint
, then&x
can be assigned to a pointer of typeint*
, and that pointer will point tox
. E.g. if you assignint* p = &x
, then*p
can be used to retrieve the value ofx
.
*
, 当用作类型的一部分时 表示该类型是指针:int
是类型,因此int*
是指向 int 类型int**
的指针,并且是指向int 类型的指针。&
当用作类型的一部分时,表示该类型是一个引用。int
是一种类型,int&
对 int 的引用也是一种类型(没有引用对引用这样的东西)。引用和指针用于类似的事情,但它们完全不同且不可互换。最好将引用视为现有变量的别名或备用名称。如果x
是int
,那么你可以简单地分配int& y = x
到创建一个新的名称y
为x
。后记x
和y
可以互换使用,指代同一个整数。这样做的两个主要含义是引用不能为 NULL(因为必须有一个原始变量来引用),并且您不需要使用任何特殊运算符来获取原始值(因为它只是一个备用名称,不是指针)。引用也不能重新分配。*
当用作一元运算符时,执行称为取消引用的操作(与引用类型无关!)。这个操作只对指针有意义。当你取消引用一个指针时,你会得到它所指向的东西。所以,如果p
是一个指针到INT,*p
是int
被指向。&
当用作一元运算符时,执行称为address-of的操作。这是不言自明的。如果x
是变量,则&x
是 的地址x
。可以将变量的地址分配给指向该变量类型的指针。因此,如果x
是int
,则&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 j
is assigned to point to a
's temporary location. Upon exit of your function the variable a
disappears, but it's former location is returned via j
. Since a
no 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 value
is initialized to zero on the first entry. All next executions of this function cause value
to 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.
这样做的缺点是你不能修改它们所指的东西——它们在构造时被绑定。