基于 http://www.cplusplus.com/reference/stl/vector/vector/
explicit vector ( const Allocator& = Allocator() );
此向量构造函数采用具有默认值Allocator()的引用参数。我从这个函数签名中学到的是函数可以使用默认值的参考参数。
这是我和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;
}
是否有一些规则来指导这种语法用法(即带有默认值的参考参数)?
答案 0 :(得分:12)
Const引用可以绑定到临时对象,在这种情况下,临时对象的生命周期延伸到引用的生命周期。
答案 1 :(得分:2)
此行为在c ++ 03的§ 8.3.6 5中定义:
默认参数表达式被隐式转换为clause 4)到参数类型。默认参数表达式与参数类型变量声明中的初始化表达式具有相同的语义约束,使用复制初始化语义(8.5)。
也就是说,const Type& var = val
只有在它也是有效的变量声明时才是有效的参数声明。根据{{3}} 5,它是。对于const Allocator& = Allocator()
,以下内容适用:
- 否则,引用应为非易失性const类型(即 cv1 应为const)。 [...]
如果初始化表达式是右值, T2 是类类型,而“ cv1 T1 ”是参考兼容的使用“ cv2 T2 ”,引用以下列方式之一绑定(选择是实现定义的):
- 引用绑定到rvalue(请参阅§ 8.5.3)或该对象中的子对象所代表的对象。
- 创建类型为“ cv2 T2 ”[sic]的临时表,并调用构造函数将整个右值对象复制到临时对象中。引用绑定到临时或临时的子对象。
无论副本是否实际完成,用于制作副本的构造函数都应该是可调用的。 [...]
否则,[...]
对于const int& iValue=5
,下一个案例适用:
- 否则,引用应为非易失性const类型(即 cv1 应为const)。 [...]
如果初始化表达式是rvalue [...]
否则,将使用非参考副本初始化的规则从初始化表达式创建并初始化类型为“ cv1 T1 ”的临时值({ {3}})。然后将引用绑定到临时。如果 T1 与 T2 的参考相关, cv1 必须与cv资格相同,或者更高的cv资格, CV2 的;否则,该计划是不正确的。 [例:
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---结束例子]
简而言之,创建了一个真实的(虽然可能是临时的)变量,因此引用可以引用它。它在参数声明中是允许的,因此参考参数可以采用默认值。否则,这将是一个不必要的限制。语言越3.10,就越容易保持在脑海中,因为你不需要记住规则的许多例外(尽管可以说,允许const引用而不是非const引用被绑定到rvalues的正交性低于不允许任何被绑定到rvalue的引用。)
答案 2 :(得分:2)
我能想到的唯一规则是(a)引用必须是const,因为你不能将非const引用绑定到临时,以及(b)它通常更好不使用const引用传递内置类型。换句话说:
(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