简体   繁体   English

返回引用并返回值

[英]Returning a reference and returning a value

I am not quite sure that I have understood why there is a problem when we return the reference of a local random variable. 我不太确定我是否理解我们返回局部随机变量的引用时为什么会有问题。 So let's say that we have this example. 所以说我们有这个例子。

int *myFunc() {
  int phantom = 4;
  return &phantom;
}

Then the usual argument is that when the function is used, the memory of the variable phantom is no longer available after the execution of the code line int phantom = 4; 那么通常的论据是,当使用该函数时,在执行代码行int phantom = 4;后,变量phantom的内存不再可用int phantom = 4; so it cannot be returned (at least this is what I have understood so far). 因此无法将其返回(至少到目前为止,这是我所了解的)。 On the other hand, for the function, 另一方面,对于功能,

int myFunc() {
  int phantom = 4;
  return phantom;
}

the value of the integer variable phantom will return. 整数变量phantom的值将返回。 (I see the returning of the value as the dereferencing of an underlying pointer for the variable phantom ). (我将值的返回视为对变量phantom的基础指针的取消引用)。

What do I miss here?? 我在这里想念什么? Why in the first case there is a compilation error and in the second case everything works?? 为什么在第一种情况下出现编译错误,而在第二种情况下一切正常?

The first doesn't return a reference, it returns a pointer. 第一个不返回引用,而是返回一个指针。 A pointer to a local variable who will go out of scope once the function ends, leaving you with a stray pointer to a variable that doesn't exist anymore. 指向局部变量的指针,一旦函数结束,该变量将超出范围,从而给您留下一个不再存在的变量的流浪指针。 That's why you get a compiler warning (usually not an actual error). 这就是为什么您会收到编译器警告 (通常不是实际错误)的原因。

The second code copies the value. 第二个代码复制该值。 The local variable inside the function will never need to be referenced or used once the return statement finished. 一旦return语句完成,函数内的局部变量将不再需要引用或使用。

You dont miss much. 你不会错过太多。 Only that in the first case there will be no compiler error. 只有在第一种情况下,才不会出现编译器错误。

[...] the memory of the variable phantom is no longer available after the execution of the code line int phantom = 4; 在执行代码行int phantom = 4之后,变量phantom的内存不再可用。 so it cannot be returned 所以不能退货

No, it can be returned and compilers may issue a warning for that but afaik no error. 不可以,它可以返回,编译器可以为此发出警告,但不会出现错误。 However, you should not!! 但是,你不应该!

Btw, the memory is available, but it is undefined behaviour to access it after the function returned (not after the line int phantom = 4; ). 顺便说一句,内存是可用的,但是在函数返回之后(不是在int phantom = 4;行之后)访问它是未定义的行为。

In the second case: 在第二种情况下:

I see the returning of the value as the dereferencing of an underlying pointer for the variable phantom 我看到值的返回是变量幻影的基础指针的取消引用

You are thinking too complicated here. 您在这里觉得太复杂了。 Returning a value from a function may be implemented by using a pointer, but thats an implementation detail. 从函数返回值可以通过使用指针来实现,但这就是实现细节。 The only thing you have to care about here is that what is returned is the value . 您唯一需要关心的是返回的 So no problems in the second case. 因此在第二种情况下没有问题。

The first case 第一种情况

int* myFunc()
{
   int phantom = 4;
   return &phantom;  // you are returning the address of phantom
}                    // but phantom will not "exist" outside of myfunc

Doesn't work because variable phantom is a local variable and it lives only during the execution of myfunc . 不起作用,因为变量phantom是局部变量,并且仅在执行myfunc期间存在。 After that, it's gone. 在那之后,它消失了。

You are returning an address of a variable, that will practically "not exist" any more. 您将返回一个变量的地址,该地址实际上将不再“存在”。

The rule: never return pointers or references to local variables. 规则:永远不要返回指针或对局部变量的引用。

This is OK: 还行吧:

 int myFunc()
 {
    int phantom = 4;
    return phantom;  // you are returning by value;
                     // it doesn't matter where phantom "lives"
 }                  

 int main()
 {
    int x = myFunc(); // the value returned by myFunc will be copied to x
 }

I am not quite sure that I have understood why there is a problem when we return the reference of a local random variable 我不太确定我是否理解我们返回局部随机变量的引用时为什么会出现问题

Because the C++ standard says it is undefined behaviour if you use such a function, and you want to avoid undefined behaviour in your program. 因为C ++标准说如果使用这样的函数,它是未定义的行为 ,并且您希望避免程序中出现未定义的行为。 What your program does should be determined by the rules of the C++ language, not be random. 您的程序要执行的操作应由C ++语言的规则决定,而不是随机的。

Note that you return a pointer and not a reference. 请注意,您返回的是指针而不是引用。 But it's undefined behaviour in both cases. 但这两种情况都是未定义的行为。

Then the usual argument is that when the function is used, the memory of the variable phantom is no longer available after the execution of the code line int phantom = 4; 那么通常的论据是,当使用该函数时,在执行代码行int phantom = 4;后,变量phantom的内存不再可用int phantom = 4; so it cannot be returned (at least this is what I have understood so far). 因此无法将其返回(至少到目前为止,这是我所了解的)。

This is an implementation-centric point of view and may aid you in understanding the problem. 这是以实现为中心的观点,可以帮助您理解问题。

Nevertheless, it's important to distinguish between the observable behaviour of a program and the compiler's internal tricks to produce that behaviour. 尽管如此,区分程序的可观察行为与编译器产生该行为的内部技巧之间的区别很重要。 You don't even know whether any memory is occupied by a variable anyway. 您甚至都不知道某个变量是否占用了任何内存。 Considering the "as-if" rule and compiler optimisations, the entire function may have been removed, even if the behaviour was defined. 考虑“假设”规则和编译器优化,即使已定义了行为,也可能已删除了整个功能。 That's just one example of what might really happen behind the scenes. 那只是幕后真正发生的事情的一个例子。

But again, it's undefined behaviour anyway, so anything may happen. 但同样,它仍然是未定义的行为,因此任何事情都可能发生。

The question is, then, why does the C++ standard not define a behaviour for the case when you return a pointer like this and then try to access the pointee? 问题是,当您返回这样的指针然后尝试访问指针时,为什么C ++标准没有为这种情况定义行为? The answer to that would be that it doesn't make sense. 答案是没有意义的。 The object named by the local variable phantom ends its life when the function returns. 函数返回时,由局部变量phantom命名的对象将终止其寿命。 So you would have a pointer to something which no longer exists, yet it's still an int* , and dereferencing a non- nullptr int* should yield an int . 因此,您将拥有一个不再存在的指针,但它仍然是一个int* ,并且取消引用非nullptr int*应该会产生一个int That's a contradiction , and the C++ standard just does not bother to resolve such a meaningless situation. 这是一个矛盾 ,而C ++标准只是不愿意解决这种无意义的情况。

Note how this observation is based on C++ language rules, not on compiler-implementation issues. 请注意,此观察结果如何基于C ++语言规则, 而不是基于编译器实现问题。

Why in the first case there is a compilation error and in the second case everything works?? 为什么在第一种情况下出现编译错误,而在第二种情况下一切正常?

It's certainly a warning and not an error , unless your compiler options are such that every warning is turned into an error. 这当然是警告,而不是错误 ,除非您的编译器选项使每个警告都变成错误。 The compiler must not reject the code, because it's not ill-formed . 编译器不得拒绝代码,因为它的格式不正确

Still, your compiler tries to be helpful in the first case, because it wants to keep you from creating a program with undefined behaviour. 尽管如此,您的编译器还是会在第一种情况下提供帮助,因为它希望阻止您创建行为未定义的程序。

In the second case, the behaviour is not undefined. 在第二种情况下,行为不是未定义的。 Returning by value means that a copy is made of the object which you want to return. 按值返回意味着您要返回的对象是一个副本 The copy is made before the original is destroyed, and the caller then receives that copy. 该副本是在销毁原始副本之前完成的,然后呼叫者会收到该副本。 That's not meaningless and not a contradiction in any way, so it's safe and defined behaviour. 这不是没有意义,也不是任何矛盾,因此它是安全且明确的行为。

In the first case, returning by value does not help you, because although the pointer itself is safely copied, its contents are what eventually causes undefined behaviour. 在第一种情况下,通过价值回归不帮你,因为虽然指针本身安全的复制,它的内容是什么最终导致不确定的行为。

Try returning the pointer and dereference it to get the value. 尝试返回指针并将其取消引用以获取该值。

#include <iostream>

using namespace std;


int *myFunc()
{

    int number = 4;
    int *phantom = &number;

    return phantom;

}

int main()
{
    cout << myFunc() << endl; //0x....
    cout << *myFunc() << endl; //4
    return 0;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM