为什么 vector 的多参数构造函数采用未标记为"explicit"的构造参数?

Why are vector's multi-argument constructors taking construction parameters not marked "explicit"?

本文关键字:参数 记为 explicit vector 构造函数 为什么      更新时间:2023-10-16

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

我想知道{ ... }在创建临时容器时总是表示容器元素的列表是否合法。这似乎是你的假设。IMO单参数构造函数需要声明为explicit,以避免不需要的转换序列或无意义的赋值,如:

vector<int> x = 3;

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

如果我真的想传入一个初始化为"hello"的由10个元素组成的向量,那么我将不得不编写f(vector(10, "hello")),而不仅仅是编写f({10, "hello"})

综上所述:虽然单参数构造函数需要声明为explicit,但我认为这对双参数值来说不是强制性的,因为不是一对大括号内的所有内容都应该被解释为容器元素列表。

而如果我省略了"foo",它就不会编译,这就是我所期望的当我将int和字符串的一对(复合)值传递给想要字符串的矢量。

不,您不传递一对int和一个字符串,但您创建了一个大小为10的向量,其中包含类似"foo"的字符串内容。上面没有错!我可以想象一些情况,在这种情况下,创建一个从一开始就包含相等字符串的向量可能是有用的。

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

好吧,这是你的问题。

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

您不应该将{10, "foo"}看作是两个值的列表。它是一个包含两个值的初始值设定项。它可以与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.