为什么vector的多参数构造函数的构造参数没有标记为“显式”?

时间:2013-02-02 17:29:50

标签: c++ c++11 constructor explicit equivalence

我在标准C ++库中观察到以下向量构造函数

explicit vector(size_type n);
vector(size_type n, const T& value, const Allocator& = Allocator());

为什么第二个构造函数没有标记为explicit?这编译,让我感觉不好

void f(vector<string>);

int main() {
  f({10, "foo"});
}

如果我省略"foo",它就不会编译,这就是我将int和字符串的一对(复合)值传递给想要一个字符串向量的函数时的预期。

3 个答案:

答案 0 :(得分:3)

我想知道在创建临时文件时,{ ... }始终表示容器元素列表是否合法。这似乎是你的假设。 IMO单参数构造函数需要被声明为explicit以避免未经考虑的转换序列或无意义的分配,例如:

vector<int> x = 3;

另一方面,对于双参数版本,唯一方式这个构造函数可以在创建临时函数时使用花括号调用,并且程序员很清楚他在那里放什么例如,我很清楚10"hello"并不代表容器元素列表,因为10不是字符串。

如果我真的想传递一个初始化为"hello"的10个元素的向量,我会因为必须编写f(vector(10, "hello"))而不是仅仅f({10, "hello"})而烦恼。

所以总结一下:虽然单参数构造函数需要声明为explicit,但我认为这对于双参数值并不是强制性的,因为不是一对花括号中的所有内容应该被解释为容器元素列表。

答案 1 :(得分:1)

  

如果我省略“foo”,它就不会编译,这就是我的期望   当我将int和string的一对(复合)值传递给想要的函数时   一串字符串。

不,你没有传递一对int和一个字符串,但你创建了一个大小为10的向量,其内容为字符串,如“foo”。它没有错!我可以想象一下,从一开始就创建一个包含相等字符串的向量可能是有用的。

答案 2 :(得分:0)

  

当我将int和string的一对(复合)值传递给想要一个字符串向量的函数时,这就是我所期望的。

嗯,这是你的问题。

{...}不是“复合值”。它不是一个清单。它说,“使用这些值初始化对象”。如果有问题的对象是聚合,它将使用聚合初始化。如果有问题的对象是非聚合类型,它将根据类型的匹配构造函数和C ++ 11中braced-init-lists的各种规则选择要调用的构造函数。

您不应将{10, "foo"}视为两个值的列表。它是一个初始化程序,包含两个值。它可以与std::pair<int, const char *>一起使用,等等。

std::vector的构造函数不明确的原因恰恰是允许这个构造。单参数构造函数是显式的,否则隐式转换规则将允许这样:

std::vector<T> v = 5; //???

或者,更重要的是:

void Foo(const std::vector<T> &v);

Foo(5); //???

我们不希望整数可以隐式转换为std::vector s。但是,当您使用初始化程序时,允许更广泛的“隐式”转换更为合理,因为您可以在那里看到{}语法。

使用单参数情况,不清楚用户的含义。使用{}语法, 清除用户的含义:初始化对象。

Foo({10, "foo"}); //Initializes the first argument given the values.