Home  >  Q&A  >  body text

c++ 临时变量问题?

#include <iostream>
#include <string>
using namespace std;

const string& Func()
{
    return "123";
}

int main()
{
    string s = Func();

    cout << s << endl;

    return 0;
}

const 引用不是会提升临时变量的生命期吗? 为什么返回函数内的临时变量会报错了? 我对const引用的理解哪里错了吗?

#include <iostream>
#include <string>
using namespace std;

const string& Func(const string& s)
{
    return s;
}

int main()
{
    string s = Func("123");

    cout << s << endl;

    return 0;
}

但是这段代码就可以了。 Func函数参数绑定到一个临时变量,然后返回这个临时变量的const引用,就没有问题?
why?

ringa_leeringa_lee2714 days ago539

reply all(5)I'll reply

  • 阿神

    阿神2017-04-17 13:34:43

    Because of the former, "123" is inside the Func function, that is, on the stack of the function. It is gone when the function is exited.
    The latter "123" means that the Func function inside the main function has been executed, and the control flow returns to the main function.
    The const reference will increase the life cycle of the temporary variable. It means that the life cycle of the temporary variable is originally just the expression that creates the temporary variable. After the expression ends, it is destructed. The const reference will increase its life cycle until the end of the function. (if it is a global const reference variable, it will naturally be promoted to the life cycle of the entire program), the function is destructed at the end, and its life cycle will not be promoted outside the function. When the function ends, it will also be destructed. of.
    Const references are actually similar to rvalue references. They both promote the life cycle of temporary variables from the expression to the function.

    Add some reference materials

    Whenever a reference is bound to a temporary or to a base subobject of a temporary, the lifetime of the temporary is extended to match the lifetime of the reference, with the following exceptions:

    • a temporary bound to a return value of a function in a return statement is not extended: it is destroyed immediately at the end of the return expression . Such function always returns a dangling reference.

    • a temporary bound to a reference member in a constructor initializer list persists only until the constructor exits, not as long as the object exists. (note: such initialization is ill-formed as of DR 1696)

    • a temporary bound to a reference parameter in a function call exists until the end of the full expression containing that function call: if the function returns a reference, which outlives the full expression, it becomes a dangling reference.( until C++14)

    • a temporary bound to a reference in the initializer used in a new-expression exists until the end of the full expression containing that new-expression, not as long as the initialized object. If the initialized object outlives the full expression, its reference member becomes a dangling reference.

    In general, the lifetime of a temporary cannot be further extended by "passing it on": a second reference, initialized from the reference to which the temporary was bound, does not affect its lifetime.

    Quoted from http://en.cppreference.com/w/cpp/language/reference_initialization

    Translate the first two paragraphs, paying special attention to the bold words:
    Whenever a reference is bound to a temporary variable or a base class subobject of a temporary variable, the life cycle of the temporary variable is extended to Corresponds to the lifetime of the reference , with the following exceptions:
    A temporary binding to the return value of the function in the return statement of the function will not be Extended : It will be destroyed immediately at the end of the return statement. Such functions always return a dangling reference.

    reply
    0
  • ringa_lee

    ringa_lee2017-04-17 13:34:43

    The main method of the first program:
    is changed to:
    const string s = Func();

    reply
    0
  • PHPz

    PHPz2017-04-17 13:34:43

    Returning local variables defined within a function is undefined behavior.

    const string& Func()
    {
        return "123";  // 返回定义在函数 Func 里的局部变量 "123",是未定义行为。
    }  // 变量 "123" 在此处被销毁
    
    int main()
    {
        string s = Func();  // s 指向已被销毁的变量
    
        cout << s << endl;
    
        return 0;
    }
    const string& Func(const string& s)
    {
        return s;  // 返回函数外定义的变量的引用 s
    }
    
    int main()
    {
        string s = Func("123");  // s 指向定义在函数 main 里的局部变量 "123"
    
        cout << s << endl;
    
        return 0;
    }  // 变量 "123" 在此处被销毁

    reply
    0
  • PHPz

    PHPz2017-04-17 13:34:43

    Const here will not increase the life cycle of local variables. Local variables are stored on the stack. When the function returns, the corresponding stack will be released, that is, the local variables will also be destroyed. Your first program is not a problem with the local variable declaration cycle. Const means it cannot be modified. However, your s variable is not modified with const, so it cannot be assigned a value.

    reply
    0
  • ringa_lee

    ringa_lee2017-04-17 13:34:43

    Personally, I think there are some problems with the above answers. . .
    Look at the question’s code:

    #include <iostream>
    #include <string>
    using namespace std;
    
    const string& Func()
    {
        return "123";
    }
    
    int main()
    {
        string s = Func();
    
        cout << s << endl;
    
        return 0;
    }

     This code will indeed report an error, but just remove the const string& Func() in &. The reason for the error is not that "123" is on the stack and is popped out of the stack when the function returns. Instead, "123" itself is in the static data area. When the function returns, what is actually returned is the address of "123" in the static data area. This address is a local variable (in the stack) in the function Func. At this time, We use the reference type to return the local variable (however, a pop operation will occur), and our reference variable will be released, and an error will occur. However, if we do not use &, what we actually get when returning is the intermediate variable of the address value (the non-reference return value of the function will be stored in the intermediate variable). At this time, the stack operation does not affect us to obtain the correct address. Worth it.

    reply
    0
  • Cancelreply