在复制列表初始化中,如果选择了一个显式构造函数,则初始化是非法的。
这就是为什么我们不能像下面这样做的原因:
struct foo {
// explicit because it can be called with one argument
explicit foo(std::string s, int x = 0);
private:
// ...
};
void f(foo x);
f({ "answer", 42 });
(注意这里发生的不是转换,即使构造函数是“隐式”的,也不是转换。这是直接使用它的构造函数初始化foo
对象。除了std::string
,这里没有其他的转换。)
我认为这看起来非常好。没有任何隐式转换会伤害到我。
如果{"answer",42}
可以初始化其他东西,编译器不会背叛我并执行错误的操作:
struct bar {
// explicit because it can be called with one argument
explicit bar(std::string s, int x = 0);
private:
// ...
};
void f(foo x);
void f(bar x);
f({ "answer", 42 }); // error: ambiguous call
没有问题:调用是模棱两可的,代码不会编译,我必须明确选择重载。
f(bar { "answer", 42 }); // ok
由于禁止明确说明,我感觉我在这里有所遗漏。就我所看到的,使用列表初始化语法选择显式构造函数似乎并不是什么问题:通过使用列表初始化语法,程序员已经表达了进行某种“转换”的愿望。
会出什么问题呢?我错过了什么吗?
{"answer", 42}
可以传递其他内容,则重载决议将是模棱两可的,因此会强制我明确指定类型。 - R. Martinho Fernandesf({"a",1});
中仍然会隐含创建一个foo
。您是否已经明确要求使用explicit
来防止这种情况发生? - Mat