开发者

Function takes a reference parameter with a default value

开发者 https://www.devze.com 2023-01-24 02:55 出处:网络
Based on http://www.cplusplus.com/reference/stl/vector/vector/ explicit vector ( const Allocator& = Allocator() );

Based on http://www.cplusplus.com/reference/stl/vector/vector/

explicit vector ( const Allocator& = Allocator() );

This vector constructor takes a reference parameter which has default value of Allocator(). What I learn from this function signature is that a function can take a reference parameter with default value.

This the demo code I play with VS2010.

#include "stdafx.h"
#include <iostream>

using namespace std;

void funA(const int& iValue=5) // reference to a template const int 5 why?
{
    cout << iValue << endl;
}

int _tmain(int argc, _TCHAR* argv[])
{
    funA();
    funA(10);
    return 0;
}

are there some rules to guide this syntax usage (i.e. a reference parameter with a开发者_如何学C default value)?


Const references may be bound to temporary objects, in which case the lifetime of the temporary extends to the lifetime of the reference.


The only rules I can think of are (a) that the reference must be const, because you can't bind a non-const reference to a temporary, and (b) that it's generally better not to use const references to pass built-in types. In other words:

(a)

void f(T& t = T(23)) {} // bad

void g(const T& t = T(23)) {} // fine

(b)

void f(const int& i = 23) {} // sort of ok

void g(int i = 23) {} // better


This behavior is defined in § 8.3.6 5 of c++03:

A default argument expression is implicitly converted (clause 4) to the parameter type. The default argument expression has the same semantic constraints as the initializer expression in a declaration of a variable of the parameter type, using the copy-initialization semantics (8.5).

That is, const Type& var = val is a valid parameter declaration only if it's also a valid variable declaration. According to § 8.5.3 5, it is. For const Allocator& = Allocator(), the following applies:

  • Otherwise, the reference shall be to a non-volatile const type (i.e., cv1 shall be const). [...]
    • If the initializer expression is an rvalue, with T2 a class type, and "cv1 T1" is reference-compatible with "cv2 T2," the reference is bound in one of the following ways (the choice is implementation defined):

      • The reference is bound to the object represented by the rvalue (see 3.10) or to a sub-object within that object.
      • A temporary of type "cv2 T2" [sic] is created, and a constructor is called to copy the entire rvalue object into the temporary. The reference is bound to the temporary or to a sub-object within the temporary.

      The constructor that would be used to make the copy shall be callable whether or not the copy is actually done. [...]

    • Otherwise, [...]

For const int& iValue=5, the next case applies:

  • Otherwise, the reference shall be to a non-volatile const type (i.e., cv1 shall be const). [...]
    • If the initializer expression is an rvalue[...]

    • Otherwise, a temporary of type "cv1 T1" is created and initialized from the initializer expression using the rules for a non-reference copy initialization (8.5). The reference is then bound to the temporary. If T1 is reference-related to T2, cv1 must be the same cv-qualification as, or greater cv-qualification than, cv2; otherwise, the program is ill-formed. [Example:

                const double& rcd2 = 2;         // rcd2  refers to temporary with value 2.0
                const volatile int cvi = 1;
                const int& r = cvi;             //  error: type qualifiers dropped
      
      ---end example]

In short, a real, though perhaps temporary, variable is created so the reference can refer to it. It's allowed in parameter declarations exactly so that reference parameters can take default values. Otherwise, it would be a needless restriction. The more orthogonal a language is, the easier it is to keep in your head, as you don't need to remember as many exceptions to the rules (though, arguably, allowing const references but not non-const references to be bound to rvalues is less orthogonal than disallowing any reference to be bound to an rvalue).

0

精彩评论

暂无评论...
验证码 换一张
取 消