C++ 函数接受具有默认值的引用参数

C++ 函数接受具有默认值的引用参数,c++,C++,基于 此向量构造函数采用具有默认值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 <<

基于

此向量构造函数采用具有默认值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;
}
#包括“stdafx.h”
#包括
使用名称空间std;
void funA(const int&iValue=5)//引用模板const int 5为什么?
{

cout常量引用可能绑定到临时对象,在这种情况下,临时对象的生存期将延长到引用的生存期。

此行为在c++03的第5部分中定义:

默认参数表达式隐式转换()为参数类型。默认参数表达式与参数类型变量声明中的初始值设定项表达式具有相同的语义约束,使用复制初始化语义()

也就是说,
const Type&var=val
仅当它也是有效的变量声明时才是有效的参数声明。根据5,它是。对于
const分配器&=Allocator()
,以下内容适用:

  • 否则,应参考非易失性常数类型(即cv1应为常数)。[…]
    • 如果初始值设定项表达式是一个右值,T2是一个类类型,“cv1 T1”与“cv2 T2”是引用兼容的,那么引用将通过以下方式之一绑定(选项由实现定义):

      • 该引用绑定到由右值表示的对象(请参见)或该对象内的子对象
      • 创建类型为“cv2 T2”[sic]的临时对象,并调用构造函数将整个右值对象复制到临时对象中。引用绑定到临时对象或临时对象中的子对象
      无论复制是否实际完成,用于制作复制的构造函数都应可调用。[…]

    • 否则,[……]

对于
const int&iValue=5
,下一种情况适用:

  • 否则,应参考非易失性常数类型(即cv1应为常数)。[…]
    • 如果初始值设定项表达式是右值[…]

    • 否则,将使用非引用副本初始化的规则()从初始值设定项表达式创建并初始化类型为“cv1 T1”的临时副本。然后将引用绑定到临时。如果T1是与T2相关的引用,则cv1的cv资格必须与cv2相同,或大于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 const double&rcd2=2;//rcd2表示值为2.0的临时值 常数volatile int cvi=1; const int&r=cvi;//错误:类型限定符已删除 ---[结束示例]

简言之,创建了一个实变量(尽管可能是临时变量),以便引用可以引用它。在参数声明中允许使用该变量,以便引用参数可以采用默认值。否则,这将是一个不必要的限制。语言越多,越容易记住,因为你不需要像人一样记住y规则的例外情况(尽管可以说,允许常量引用但不允许非常量引用绑定到右值比不允许任何引用绑定到右值更不正交)。

我能想到的唯一规则是(a)引用必须是常量,因为不能将非常量引用绑定到临时引用,以及(b)通常最好不要使用常量引用来传递内置类型。换句话说:

(a)

(b)


你对什么感到困惑,你认为规则可能会澄清?语法对我来说似乎很清楚,因此,我不知道如何帮助你。为什么允许引用局部临时变量有意义?我假设引用应该总是指向一些真实变量。-谢谢,那怎么会不那么“真实”呢那么,一个单独存在于函数中的变量?它只是没有命名,并且在函数返回时立即超出范围。这是否意味着引用必须是左值,而常量引用可以是右值和左值?@dreamlax:确实如此。在C++03中,修改右值是未定义的行为,我相信,这就是为什么引用必须是常量。@dreamlax:不完全正确。左值和右值指的是语法表达式(在C++98中,表达式必须是左值或右值)。这种区别起源于C,其中右值的点(C非左值)简单来说,产生值的表达式是一个右值表达式,而产生值的表达式是一个引用内存中某个对象的表达式(引用类型的表达式必然会这样做)是一个LValk表达式。希望我没有过度简化,@ DeLMG:也不完全一样。考虑<代码> STD::String(“UH”)[0 ]。='o'
。这是对右值的完美定义修改,C++98支持对类类型的右值表达式调用成员函数。具有讽刺意味的是,由于自动生成赋值op member func,您可以像
f()=structValue
那样执行,但不能像
f().intMember=42
。整个概念只是有点缺陷…;-)好吧,现在我觉得《独立日》电影中的总统顾问--“不完全是…”:-)无法编辑之前的评论,所以,我指的是数据存储位置。机码当然也在内存中。标准还有许多其他部分(例如§4,12.2)这定义了引用参数默认值的其他行为方面,但我认为它们不会影响语法,这正是这个问题所关注的 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
void f(T& t = T(23)) {} // bad

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

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