简体   繁体   English

为什么向量的多参数构造函数采用未标记为“显式”的构造参数?

[英]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.

相关问题 何时为多参数构造函数使用显式说明符? - When to use explicit specifier for multi-argument constructors? SWIG 多参数类型映射适用于函数,但如果有多个构造函数则不适用于构造函数 - A SWIG multi-argument typemap apply to functions, but not to the constructor if there's multiple constructors 使用引用参数的构造函数的显式修饰符 - Explicit modifier for constructors taking reference argument 一对向量构造函数:初始化列表与显式构造 - Pair of vector constructors: initializer list vs explicit construction 字符串的复杂多参数#define宏 - Complicated multi-argument #define macro for strings 多参数宏定义错误 - Multi-Argument macro definition error 为什么带有unsigned long long参数的std :: bitset构造函数未标记为显式? - Why is the std::bitset constructor with an unsigned long long argument not marked as explicit? 如何将多参数模板传递给宏? - How to pass multi-argument templates to macros? 排除使用显式构造的std :: pair构造函数 - Excluding std::pair constructors that use explicit construction 为什么std :: list中的单个参数构造函数定义为显式 - Why single argument constructors in std::list defined as explicit
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM