为什么 vector 的多参数构造函数采用未标记为"explicit"的构造参数?
Why are vector's multi-argument constructors taking construction parameters not marked "explicit"?
我在标准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::vector
s。但是,当您使用初始值设定项时,允许更广泛的"隐式"转换更合理,因为您可以在那里看到{}
语法。
对于单参数的情况,还不清楚用户的意思。使用{}语法,就清楚了用户的意思:初始化对象。
Foo({10, "foo"}); //Initializes the first argument given the values.
- lambda参数转换为constexpr技巧,然后获取带链接的数组
- MSVC将仅移动结构参数解释为指针
- 如何将可变长度参数联接为字符串
- 如何检查给定的参数是否为 cv::noArray()?
- 将参数传递为"const"的奇怪效果
- 使用 C++ 将命令行参数拆分为参数/向量
- 如何将向量中的可变参数转换为参数的持有者?
- c++ 构造函数 将 1 个字符串参数转换为 3 个属性
- 将空*参数转换为各种类型的参数是UB吗?
- 如何在使用 Qt5 构造函数时将非常量参数修改为常量参数?
- 使函数参数默认为周围范围
- 将可变参数模板参数转换为 JSON 字符串
- 如何使用类型特征将函数的通用引用参数限制为 r 值引用?
- 了解'this'或其他参数是否为右值
- 为什么无法在可变参数模板中将尾随模板参数指定为默认值?
- 为什么 std::error_code 构造函数的第一个参数固定为 int
- C++ 如何将函数参数转换为字符串
- 使用 std::move 将参数传递给函数,如果该参数声明为按值传递或使用移动操作数 &&,是否有区别?
- 如何检查模板参数是否为给定值?
- 是否可以将参数固定为可变参数模板函数?