const reference default-value

30,847

Solution 1

You can't take a non-const reference to a temporary like foo2 does.

Notice that this isn't specifically default parameters. You get the same error for function variables: http://ideone.com/g7Tf7L

#include <string>
using std::string;

#include <iostream>
using std::cout; using std::endl;

int main()
{
    string s1        = string("s1"); // OK, copy it
    const string& s2 = string("s2"); // OK, const reference to it
    string& s3       = string("s3"); // ERROR! non-const reference not allowed!

    cout
            << s1 << ", "
            << s2 << ", "
            << s3 << endl;
    return 0;
}

When you take a const reference to a temporary, the lifetime of the temporary is extended to the lifetime of the reference (§12.2, quoted from my copy of C++11 draft n3337):

There are two contexts in which temporaries are destroyed at a different point than the end of the fullexpression.

...

The second context is when a reference is bound to a temporary. The temporary to which the reference is bound or the temporary that is the complete object of a subobject to which the reference is bound persists for the lifetime of the reference except:

  • A temporary bound to a reference member in a constructor’s ctor-initializer (12.6.2) persists until the constructor exits.
  • A temporary bound to a reference parameter in a function call (5.2.2) persists until the completion of the full-expression containing the call.
  • The lifetime of a temporary bound to the returned value in a function return statement (6.6.3) is not extended; the temporary is destroyed at the end of the full-expression in the return statement.
  • A temporary bound to a reference in a new-initializer (5.3.4) persists until the completion of the full-expression containing the new-initializer.

Solution 2

It may come as a surprise to you, but you can bind the value of a temporary expression to a constant reference, and the lifetime of the expression is extended to that of the reference. But you cannot do this with a non-constant (lvalue) reference.

Share:
30,847
aiao
Author by

aiao

Embedded Software Engineer. Areas of expertise: AUTOSAR, Linux, Yocto, information security, dynamic controls and drones.

Updated on January 31, 2020

Comments

  • aiao
    aiao over 4 years

    Possible Duplicate:
    how to initialize function arguments that are classes with default value

    #include <string>
    
    void foo1(const std::string& s = std::string());
    
    void foo2(std::string& s = std::string());
    
    void foo3(const std::string s = std::string());
    
    void foo4(std::string s = std::string());
    

    error at foo2(): default argument for ‘std::string& s’ has type ‘std::string {aka std::basic_string<char>}’

    I understand the compiler's point, but I don't get how this does not apply to foo1() as well.

  • aiao
    aiao over 11 years
    1. Can you elaborate (or direct me somewhere), why not, but ok to take for const reference 2. what is the life time of this temporary?
  • David Schwartz
    David Schwartz over 11 years
    Consider void myAbs(int &j) { if (j < 0) j = -j; } short q; ... myAbs(q);. This would (if it were allowed) create a temporary int, set it to its absolute value, then destroy it leaving q unchanged. Yuck. The const promises the compiler you're not going to do that.
  • aiao
    aiao over 11 years
    what is the life time for this temporary in foo3() and foo4()?
  • Johannes Schaub - litb
    Johannes Schaub - litb over 11 years
    @aiao the lifetime in all cases is that of the calling full expressions evaluation time. a reference function parameter does not lengthen the lifetime of an argument, nor does it shorten it.
  • Remy Lebeau
    Remy Lebeau over 11 years
    In C++11, you can haave a non-const reference to a temporary if you use an rvalue reference. foo2() in this example is using an lvalue reference instead.
  • Kerrek SB
    Kerrek SB over 11 years
    @aiao: The lifetime of the temporary is the lifetime of the full-expression in which it occurs. It's actually the same for foo1 and foo3, but if foo3 the temporary is only used to copy-initialize the variable s.
  • jaques-sam
    jaques-sam about 4 years
    Does foo1 work when called from another dynamic library? I hear a colleague had trouble with this, but can't confirm.
  • dragonxlwang
    dragonxlwang over 3 years
    and to be more precise, only local const reference can prolongs the lifetime of a temporary, with exceptions. Class initialization of const reference does not do so. stackoverflow.com/questions/2784262/…