考虑以下构造函数:
class MyClass {
MyClass(unsigned int dimension, std::vector vector=unitaryVector(dimension));
};
其中unitaryVector(d)
是一个在d维中返回随机std::vector
的函数。
这会产生以下编译器错误:
error: default argument references parameter 'dimension'
MyClass(unsigned int dimension, std::vector vector=unitaryVector(dimension));
为什么这个成语在C ++ 11中无效?这似乎很明显:如果提供了vector
参数,则将init vector
作为参数的副本,否则,调用该函数并将其作为返回值的副本进行初始化。为什么编译器不能理解这一点?
答案 0 :(得分:9)
C ++标准禁止它。
每次调用函数时都会计算9默认参数 没有相应参数的参数。参数不得 在默认参数中显示为可能已评估的表达式。 在默认参数之前声明的函数的参数 范围,可以隐藏命名空间和类成员名称。
[例如:
int a; int f(int a, int b = a); // error: parameter a // used as default argument typedef int I; int g(float I, int b = I(2)); // error: parameter I found int h(int a, int b = sizeof(a)); // OK, unevaluated operand
- 结束示例]
请注意,如果未提供
,则默认参数在呼叫站点替换Intro.execution (强调我的)
11: [注意:对 完整表达式 的评估可以包括对子表达式的评估不是词汇的一部分 全表达即可。例如,参与评估的子表达式 默认参数([dcl.fct.default])被认为是创建的 在调用函数的表达式中,不是表达式 定义默认参数。 - 结束说明]
您可以简单地重载构造函数并委托它:
class MyClass {
explicit MyClass(unsigned int dimension)
: MyClass(dimension, unitaryVector(dimension)) //delegation
{ }
MyClass(unsigned int dimension, std::vector vector);
};
脚注:制作单个参数构造函数是一件好事explicit
答案 1 :(得分:2)
另一种方法是使用
class MyClass {
MyClass(unsigned int dimension, std::vector const& vector) :
dimension(dimension), vector(vector) {}
MyClass(unsigned int dimension) :
MyClass(dimension, unitaryVector(dimension)) {}
};
(当然,当你想在课堂上存储dimension
和vector
时)。
答案 2 :(得分:1)
因为默认参数本身必须是完整的,所以如果没有通过调用提供,编译器可以简单地替换它。 (本地)变量dimension
尚未创建,您正在尝试使用它,因此也就是错误。然而,这可行:
int _def_dim=10;
class MyClass {
MyClass(unsigned int dimension, std::vector vector=unitaryVector(_def_dim));
};
我不确定标准是什么,但是对于编译器实现来说,处理这种极端情况会很棘手。
编辑(完整性),从this answer抓取:
每次调用函数时都会计算默认参数。该 函数参数的评估顺序未指定。 因此,默认情况下不应使用函数的参数 参数表达式,即使它们未被评估。