24

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.

Community
  • 1
  • 1
aiao
  • 4,621
  • 3
  • 25
  • 47
  • 2
    You can do `= {}` instead of `= std::string()` to save space. – chris Jan 30 '13 at 20:21
  • 1
    Even the good old `= ""` will work and requires less typing. – David Rodríguez - dribeas Jan 30 '13 at 20:31
  • I think the answers are confusing (and informative). The simple answer is that you are right in essence. A reference is supposed to work a lot like a pointer in a sense. You obviously can't point to a temporary. You normally point to some spot in memory where you stored a value of interest. For some convenience, the const refs were "extended" to be able to point to a temporary. – AturSams Nov 18 '15 at 09:47
  • 1
    In essence, the whole purpose of a function that accepts a none-const ref is to *modify* what it's refing to (otherwise it'd be a **const** ref) so it should not make any sense to you when you want a *default value* for a non-const ref. What you may want is to overload with a version of the function that does not accept any input. – AturSams Nov 18 '15 at 09:52
  • 1
    In other words when we don't specify const, we care about where (address) the value is stored just as much as we care about that value itself (sometimes more). With const ref we (normally) probably do not care at all about where the value is stored. – AturSams Nov 18 '15 at 11:20

3 Answers3

27

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.
Johannes Schaub - litb
  • 496,577
  • 130
  • 894
  • 1,212
Bill
  • 14,257
  • 4
  • 43
  • 55
  • 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? – aiao Jan 30 '13 at 20:26
  • 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. – David Schwartz Jan 30 '13 at 20:27
  • 6
    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. – Remy Lebeau Jan 30 '13 at 20:39
  • Does `foo1` work when called from another dynamic library? I hear a colleague had trouble with this, but can't confirm. – jaques-sam Mar 25 '20 at 09:05
6

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.

Kerrek SB
  • 464,522
  • 92
  • 875
  • 1,084
  • what is the life time for this temporary in `foo3()` and `foo4()`? – aiao Jan 30 '13 at 20:28
  • 1
    @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. – Johannes Schaub - litb Jan 30 '13 at 20:32
  • 2
    @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`. – Kerrek SB Jan 30 '13 at 20:39
  • 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. https://stackoverflow.com/questions/2784262/does-a-const-reference-class-member-prolong-the-life-of-a-temporary – dragonxlwang Jan 05 '21 at 21:55
1

The declarations of foo3 and foo4 are legal because the argument to those functions is not a reference.

The declaration of foo2 is illegal because you can't bind a non-const reference to a temporary.

So why is the declaration of foo1 legal? It's that very important const qualifier that makes this declaration legal.

David Hammen
  • 32,454
  • 9
  • 60
  • 108