10

我在标准 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 和一个字符串的对(复合)值传递给一个需要字符串向量的函数时,这就是我所期望的。

4

3 回答 3

3

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

vector<int> x = 3;

另一方面,对于双参数版本,在创建临时文件时调用此构造函数的唯一方法是使用花括号,并且程序员很清楚他在其中放入了什么。例如,我很清楚,10并且"hello"并不意味着表示容器元素列表,因为10它不是字符串。

如果我真的想传入一个初始化为 10 个元素的向量"hello",我会因为不得不写f(vector(10, "hello"))而不是只做f({10, "hello"}).

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

于 2013-02-02T18:06:27.470 回答
1

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

不,您没有传递一对 int 和一个字符串,而是创建了一个大小为 10 的向量,其中包含诸如“foo”之类的字符串内容。它没有任何问题!我可以想出一些情况,从一开始就创建一个包含相等字符串的向量可能很有用。

于 2013-02-02T17:43:50.023 回答
0

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

嗯,有你的问题。

{...}不是“复合值”。它不是一个列表。它说,“使用这些值初始化一个对象”。如果有问题的对象是一个聚合,它将使用聚合初始化。如果所讨论的对象是非聚合类型,它将根据类型的匹配构造函数和 C++11 中花括号初始化列表的各种规则来选择要调用的构造函数。

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

的构造函数不显式的原因std::vector正是为了允许这种构造。单参数构造函数是显式的,否则,隐式转换规则将允许这样做:

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

或者,更重要的是:

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

Foo(5); //???

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

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

Foo({10, "foo"}); //Initializes the first argument given the values.
于 2013-02-02T20:47:10.610 回答