对于C++中的默认参数,值是必须是常量还是另一个参数呢?
也就是说,以下工作可以吗?
RateLimiter(unsigned double rateInPermitsPerSecond,
unsigned int maxAccumulatedPermits = rateInPermitsPerSecond);
Run Code Online (Sandbox Code Playgroud)
目前我收到一个错误:
RateLimiter.h:13:错误:'rateInPermitsPerSecond'未在此范围内声明
Ale*_*exD 78
另一个参数不能用作默认值.标准规定:
8.3.6默认参数
...
9每次调用函数时都会计算默认参数,且相应参数没有参数.函数参数的评估顺序未指定.因此,函数的参数不应在默认参数中使用,即使它们未被评估.
并用以下示例说明:
int f(int a, int b = a); // error: parameter a
// used as default argument
Run Code Online (Sandbox Code Playgroud)
Bau*_*gen 73
不,这不起作用,因为函数参数的评估没有排序.它也不起作用,因为标准不允许它,但我想这很明显.
改为使用过载:
void fun(int, int) {}
void fun(int i) {
fun(i, i);
}
Run Code Online (Sandbox Code Playgroud)
Ric*_*ges 36
我正在寻找一个合理的解释,为什么不允许它
这实际上是一个很好的问题.原因是C++没有强制要求评估参数的顺序.
所以让我们想象一个稍微复杂的场景:
int f(int a, int b = ++a);
... followed by ...
int a = 1;
f(a);
Run Code Online (Sandbox Code Playgroud)
C++没有强制要求评估参数的顺序,还记得吗?
那么b的价值应该是多少?
f(a) 可评估为:
f(1, 2),或者
f(2, 2),取决于参数的评估顺序.
因此行为将是未定义的(甚至是不可定义的).
此外,考虑当a和b是构造函数和复制运算符具有副作用的复杂对象时可能发生的情况.
这些副作用的顺序将是不确定的.
Mar*_*wen 11
你不能做那样的事情,因为标准不允许这样做.但是,由于默认参数实际上只是定义了新的函数重载,因此可以通过显式定义这样的重载来获得所需的效果:
void RateLimiter(unsigned int rateInPermitsPerSecond,
unsigned int maxAccumulatedPermits);
inline void RateLimiter(unsigned int rateInPermitsPerSecond)
{ return RateLimiter(rateInPermitsPerSecond,rateInPermitsPerSecond); }
Run Code Online (Sandbox Code Playgroud)
这表明禁止这种做法的标准是半心半意的,正如语言所暗示的那样("因此......不应......").他们只是不想经历使得这个定义得很好的麻烦,其效果与显式重载声明的作用相同:如果需要,他们可以指定默认参数在明确提供的参数之后进行评估,并且从左到右.这对函数调用中参数表达式的求值顺序未指定的规则没有任何影响(因为默认参数不对应于这样的表达式;它们是完全独立的,甚至不在相同的词法范围内).另一方面,如果(正如他们所做的那样)他们宁愿不允许这样做,他们可能只是说"不应该",而不需要从其他规则中证明自己(但可能有解释性脚注).