可以使用另一个参数初始化C++默认参数吗?

use*_*858 58 c++

对于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是构造函数和复制运算符具有副作用的复杂对象时可能发生的情况.

这些副作用的顺序将是不确定的.

  • @Mzn未定义的行为,如果它是合法的,它不是. (4认同)

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)

这表明禁止这种做法的标准是半心半意的,正如语言所暗示的那样("因此......不应......").他们只是不想经历使得这个定义得很好的麻烦,其效果与显式重载声明的作用相同:如果需要,他们可以指定默认参数在明确提供的参数之后进行评估,并且从左到右.这对函数调用中参数表达式的求值顺序未指定的规则没有任何影响(因为默认参数不对应于这样的表达式;它们是完全独立的,甚至不在相同的词法范围内).另一方面,如果(正如他们所做的那样)他们宁愿不允许这样做,他们可能只是说"不应该",而不需要从其他规则中证明自己(但可能有解释性脚注).