C ++中的范围和返回值

时间:2008-11-08 21:16:46

标签: c++ return-value scope

我将重新开始使用c ++并考虑变量的范围。 如果我在一个函数中有一个变量然后我返回该变量,那么当它返回时变量不会“死”,因为它所在的范围已经结束了?

我试过这个函数返回一个字符串,它确实有效。 有谁能解释一下?或者至少指出一些可以向我解释的地方。

由于

6 个答案:

答案 0 :(得分:42)

  

当函数终止时,   发生以下步骤:

     
      
  • 函数的返回值是   复制到占位符中   为此目的放在堆栈上。

  •   
  • 堆叠帧后的所有内容   指针弹出。这破坏了   所有局部变量和参数。

  •   
  • 从中弹出返回值   堆栈并被指定为值   功能。如果是的价值   功能没有分配给任何东西,   没有任务,而且   价值丢失。

  •   
  • 下一条指令的地址   执行从弹出栈,   并且CPU恢复执行   那条指令。

  •   

The stack and the heap

答案 1 :(得分:3)

返回值时,会复制一份。局部变量的范围结束,但会复制并返回到调用函数。例如:

int funcB() {
  int j = 12;
  return j;
}

void A() {
  int i;
  i = funcB();
}

将j(12)的值复制并返回给i,这样我将收到12的值。

答案 2 :(得分:3)

这实际上取决于您返回的变量类型。如果返回一个原语,则它是通过复制而不是通过引用返回的,因此该值被复制到堆栈的顶部(或者,更常见的是放入寄存器中),调用函数可以在其中获取它。如果在堆上分配一个对象或内存并返回一个指针,那么它就不会因为它在堆上而不是堆栈而死亡。但是,如果你在堆栈上分配一些东西并返回它,那将是一件坏事。例如,其中任何一个都非常糟糕:

int *myBadAddingFunction(int a, int b)
{
    int result;

    result = a + b;
    return &result; // this is very bad and the result is undefined
}

char *myOtherBadFunction()
{
    char myString[256];

    strcpy(myString, "This is my string!");
    return myString; // also allocated on the stack, also bad
}

答案 3 :(得分:3)

仅仅是针对面向内存模型的解释:当调用函数时,会为函数创建一个临时空间来放置其局部变量,称为 frame 。当函数(被调用者)返回其值时,它将返回值放在调用它的函数的框架中(调用者),然后销毁被调用者框架。

“框架被破坏”部分是您无法从函数返回指针或对局部变量的引用的原因。指针实际上是一个内存位置,因此一旦框架被销毁,返回局部变量的内存位置(根据定义:框架内的变量)就会变得不正确。由于被调用者帧一返回其值就被销毁,所以对局部变量的任何指针或引用都会立即错误。

答案 4 :(得分:2)

将局部变量复制到返回值。复制构造函数被调用用于非平凡的类。

如果您返回指向本地变量的指针或引用,您将遇到麻烦 - 正如您的直觉所暗示的那样。

答案 5 :(得分:2)

这取决于返回项目的类型。如果按值返回,则会生成变量的新副本以返回给调用者。在这种情况下你不需要担心对象的生命周期,但你可能需要担心复制对象的成本(但请不要过早地优化 - 正确性更重要):

std::string someFunc( std::string& const s)
{
    return s + "copy";
}

如果函数返回一个引用,那么你需要注意你要返回的内容,因为它的生命周期需要超出函数的生命周期,如果你的话,调用者不一定能够delete它'使用new创建对象:

std::string& someFunc2( std::string const& s)
{
    return s + "reference to a copy";   // this is bad - the temp object created will 
                                        //  be destroyed after the expression the 
                                        //  function call is in finishes.
                                        //  Some, but not all, compilers will warn 
                                        //  about this.
}

当然,返回指针也会有类似的生命周期考虑因素。