Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

const reference default-value [duplicate]

Tags:

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.

like image 710
aiao Avatar asked Jan 30 '13 20:01

aiao


People also ask

Does const reference make a copy?

Not just a copy; it is also a const copy. So you cannot modify it, invoke any non-const members from it, or pass it as a non-const parameter to any function. If you want a modifiable copy, lose the const decl on protos .

CAN default arguments be const?

Default arguments are different from constant arguments as constant arguments can't be changed whereas default arguments can be overwritten if required. Default arguments are overwritten when the calling function provides values for them.

What will be the default value for reference variables?

What will be the initial value of an object reference which is defined as an instance variable? The object references are all initialized to null in Java.

Can you change the value of const reference?

Because the reference is a const reference the function body cannot directly change the value of that object. This has a similar property to passing by value where the function body also cannot change the value of the object that was passed in, in this case because the parameter is a copy.


2 Answers

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.
like image 185
Bill Avatar answered Oct 08 '22 05:10

Bill


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.

like image 39
Kerrek SB Avatar answered Oct 08 '22 06:10

Kerrek SB