#include <vector>
using std::size_t;
struct Foo
{
Foo(size_t i, char c) {}
};
Foo Bar1()
{
size_t i = 0;
char c = 'x';
return { i, c }; // good
}
std::vector<char> Bar2()
{
size_t i = 0;
char c = 'x';
return { i, c }; // bad
}
https://wandbox.org/permlink/87uD1ikpMkThPTaw
警告:缩小'i'与'std :: size_t {aka long'的转换 unsigned int}'to'char'in {}
显然它试图使用vector的initializer_list。但为什么不使用更好的匹配vector<char>(size_t, char)
?
我可以在return语句中使用所需的构造函数而无需再次编写类型吗?
答案 0 :(得分:4)
因为initializer_list构造函数(如果可能的话)优先于其他构造函数。这样可以减少边缘情况 - 特别是,您希望它使用的特定向量构造函数被认为是偶然选择的。
具体来说,标准在16.3.1.7“按列表初始化初始化”[over.match.list](最新草案,N4687)中说:
(1)当非聚合类类型T的对象被列表初始化时,11.6.4指定根据本节中的规则执行重载解析,重载决策分两个阶段选择构造函数:
- 最初,候选函数是类T的初始化列表构造函数(11.6.4),参数列表由初始化列表作为单个参数组成。
- 如果找不到可行的初始化列表构造函数,则再次执行重载解析,其中候选函数是类T的所有构造函数,参数列表由初始化列表的元素组成。
因此,如果您执行std::vector<char>( i, c )
,则此部分根本不适用,因为它不是列表初始化。应用正常的重载分辨率,找到并使用(size_t, char)
构造函数。
但是如果你做std::vector<char>{ i, c }
,这就是列表初始化。首先尝试初始化列表构造函数,(initializer_list<char>)
构造函数是匹配的(即使它涉及从size_t
到char
的缩小转换),因此在大小+值之前使用它构造函数一直被考虑。
所以回答编辑过的问题:不,你不能在没有命名其类型的情况下创建矢量。但是在C ++ 17中,您可以使用类模板参数推导,只需编写return std::vector(i, c);