代码之家  ›  专栏  ›  技术社区  ›  cpx

返回对局部或临时变量的引用[重复]

c++
  •  41
  • cpx  · 技术社区  · 14 年前

    请看下面的代码。我知道它不返回局部变量的地址,但是为什么它仍然工作并分配变量 i 在main()到“6”中?如果变量从堆栈内存中删除,它如何只返回值?

    #include <iostream>
    
    int& foo()
    {
        int i = 6;
        std::cout << &i << std::endl; //Prints the address of i before return
        return i;
    }
    
    int main()
    {
        int i = foo();
        std::cout << i << std::endl; //Prints the value
        std::cout << &i << std::endl; //Prints the address of i after return
    }
    
    5 回复  |  直到 14 年前
        1
  •  23
  •   Marcelo Cantos    14 年前

    你很幸运。从函数返回不会立即擦除刚退出的堆栈帧。

    顺便问一句,你是如何确认你得到了6分?表达式 std::cout << &i ... 打印的地址 i 不是它的价值。

        2
  •  3
  •   NeuroScr    14 年前

    一定是编译器正在做的事情。

    http://www.learncpp.com/cpp-tutorial/74a-returning-values-by-value-reference-and-address/

    确认示例将从堆栈内存中删除引用。

        3
  •  3
  •   Community Sam Holder    7 年前

    返回对局部变量的引用或指针是未定义的行为。未定义的行为意味着,标准将决定权留给编译器。这意味着,未定义的行为有时会很好地工作,并且 sometimes it doesn't .

        4
  •  2
  •   John Dibling    14 年前

    地址 i 永远不会改变 main() 但其中包含的价值将是。您正在获取局部变量的引用,并在该引用超出范围后使用它。(不精确的语言警告)值 6 在堆栈上。因为你放完东西后没有做任何处理 在那里,对它的引用仍然包含相同的值。所以,正如其他人所说,你很幸运。

    要知道有多幸运,请尝试在调用后运行使用堆栈的代码。 foo() :

    #include <iostream>
    #include <ctime>
    #include <numeric>
    
    int& foo()
    {
        int i = 6;
        std::cout << &i << " = " << i << std::endl; //Prints the address of i before return
        return i;
    }
    
    long post_foo(int f)
    {
        srand((unsigned)time(0));
    
        long vals[10] = {0};
        size_t num_vals = sizeof(vals)/sizeof(vals[0]);
        for( size_t i = 0; i < num_vals; ++i )
        {
            int r = (rand()%2)+1;
            vals[i] = (i+f)*r;
        }
    
        long accum = std::accumulate(vals, &vals[num_vals], 0);
        return accum * 2;
    }
    
    int main()
    {
        int &i = foo();
    //  std::cout << "post_foo() = " << post_foo(i) << std::endl;
        std::cout << &i << " = " << i << std::endl; 
    }
    

    当我用 post_foo() 呼叫被取消, 仍在堆栈中,输出为:

    002CF6C8 = 6
    002CF6C8 = 6
    

    …但当我取消对呼叫的评论时 Posil英尺() 又跑了一遍, 早已逝去:

    001FFD38 = 6
    post_foo() = 310
    001FFD38 = 258923464
    
        5
  •  1
  •   John Gordon    14 年前

    当您的函数通过引用返回一个整数时,它会立即分配给main()中的局部变量“i”。这意味着为foo()分配的堆栈内存必须保持足够长的时间才能进行返回分配。虽然这是不好的形式,但通常是有效的。如果你想保留一份推荐信

    int &i = foo();
    

    它更有可能失败。