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