[英]Why are vector's multi-argument constructors taking construction parameters not marked "explicit"?
I observed the following vector constructors in the Standard C++ library我在标准 C++ 库中观察到以下向量构造函数
explicit vector(size_type n);
vector(size_type n, const T& value, const Allocator& = Allocator());
Is there a reason why the second constructor is not marked explicit
?第二个构造函数没有标记为
explicit
的原因吗? This compiles, and makes me feel bad这编译,让我感觉不好
void f(vector<string>);
int main() {
f({10, "foo"});
}
While if I omit the "foo"
, it doesn't compile and that is what I expect when I pass a pair (compound) value of an int and a string to a function that wants a vector of strings.虽然如果我省略
"foo"
,它不会编译,这就是我将 int 和字符串的对(复合)值传递给需要字符串向量的 function 时所期望的。
I'm wondering whether it is legitimate in the first place to expect that {... }
always represents a list of container elements when creating a temporary.我想知道在创建临时对象时期望
{... }
始终代表容器元素列表是否合法。 This seems to be your assumption.这似乎是你的假设。 IMO the one-argument constructor needs to be declared as
explicit
to avoid undesidered conversion sequences or meaningless assignments such as: IMO需要将单参数构造函数声明为
explicit
以避免意外的转换序列或无意义的分配,例如:
vector<int> x = 3;
On the other hand, for the two-argument version, the only way this constructor can be called when a temporary is created is with the use of curly braces, and the programmer is well aware of what he's putting in there.另一方面,对于双参数版本,在创建临时变量时调用此构造函数的唯一方法是使用花括号,并且程序员很清楚他在其中放入了什么。 For instance, it is quite clear to me that
10
and "hello"
are not meant to represent a list of container elements, because 10
is not a string.例如,我很清楚
10
和"hello"
并不是要表示容器元素的列表,因为10
不是字符串。
If I really wanted to pass in a vector of 10 elements initialized to "hello"
, I would be bothered by having to write f(vector(10, "hello"))
instead of just doing f({10, "hello"})
.如果我真的想传入一个初始化为
"hello"
的 10 个元素的向量,我会因为不得不写f(vector(10, "hello"))
而不是只写f({10, "hello"})
.
So to sum it up: while the one-argument constructor needs to be declared as explicit
, I believe this is not mandatory for the two-argument value, because not everything which is inside a pair of curly braces should be interpreted as a list of container elements.所以总结一下:虽然需要将单参数构造函数声明为
explicit
,但我相信这对于双参数值不是强制性的,因为并非一对花括号内的所有内容都应解释为容器元素。
While if I omit the "foo", it doesn't compile and that is what I expect when I pass a pair (compound) value of an int and a string to a function that wants a vector of strings.
虽然如果我省略“foo”,它不会编译,这就是我将 int 和字符串的一对(复合)值传递给需要字符串向量的 function 时所期望的。
No, you don't pass a pair of int and a string but you create a vector of size 10 with content of strings like "foo".不,您没有传递一对 int 和一个字符串,而是创建了一个大小为 10 的向量,其中包含诸如“foo”之类的字符串内容。 There is nothing wrong on it.
它没有错。 I can figure some situation where it may be usefull to create a vector contains the equal strings from the beginning
我可以想出一些情况,从一开始就创建一个包含相等字符串的向量可能很有用
that is what I expect when I pass a pair (compound) value of an int and a string to a function that wants a vector of strings.
当我将 int 和字符串的一对(复合)值传递给需要字符串向量的 function 时,这就是我所期望的。
Well, there's your problem.嗯,有你的问题。
{...}
is not a "compound value". {...}
不是“复合值”。 It is not a list.它不是一个列表。 It says, "initialize an object using these values".
它说,“使用这些值初始化 object”。 If the object in question is an aggregate, it will use aggregate initialization.
如果所讨论的 object 是一个聚合,它将使用聚合初始化。 If the object in question is a non-aggregate type, it will pick a constructor to call, based on the matching constructors of the type and the various rules for braced-init-lists in C++11.
如果所讨论的 object 是非聚合类型,它将根据类型的匹配构造函数和 C++11 中花括号初始化列表的各种规则来选择要调用的构造函数。
You shouldn't think of {10, "foo"}
as a list of two values.您不应将
{10, "foo"}
视为两个值的列表。 It is an initializer that contains two values.它是一个包含两个值的初始化程序。 It could be used with a
std::pair<int, const char *>
, and so forth.它可以与
std::pair<int, const char *>
等一起使用。
The reason why std::vector
's constructor isn't explicit is precisely to allow this construct. std::vector
的构造函数不明确的原因正是为了允许这种构造。 The single-argument constructor is explicit because otherwise, implicit conversion rules would allow this:单参数构造函数是显式的,否则,隐式转换规则将允许这样做:
std::vector<T> v = 5; //???
Or, more importantly:或者,更重要的是:
void Foo(const std::vector<T> &v);
Foo(5); //???
We don't want integers to be implicitly convertible to std::vector
s.我们不希望整数隐式转换为
std::vector
。 However, when you're using an initializer, it's more reasonable to allow a wider range of "implicit" conversions, because you can see the {}
syntax there.但是,当您使用初始化程序时,允许更广泛的“隐式”转换更合理,因为您可以在那里看到
{}
语法。
With the single-argument case, it isn't clear what the user means.对于单参数情况,不清楚用户的意思。 With the {} syntax, it is clear what the user means: to initialize the object.
使用 {} 语法,用户的意思很清楚:初始化 object。
Foo({10, "foo"}); //Initializes the first argument given the values.
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.