vector<T>
有一个构造函数,它取了向量的大小,据我所知它是 explicit ,这可以通过以下代码无法编译的事实证明
void f(std::vector<int> v);
int main()
{
f(5);
}
我无法理解并要求您解释为什么以下代码编译
std::vector<std::vector<int>> graph(5, 5);
它不仅编译,它实际上将图形大小调整为5并将每个元素设置为五个零的向量,即与我通常编写的代码相同:
std::vector<std::vector<int>> graph(5, std::vector<int>(5));
如何?为什么呢?
编译器:MSVC10.0
答案 0 :(得分:7)
这不是一个真正的错误。问题是在第一段代码不能编译时允许第二段代码可能出错?
问题在于,当您执行以下操作时,您想要调用的构造函数似乎很明显:
std::vector<std::vector<int>> graph(5, 5);
编译器不太清楚。特别是有两个构造函数重载可以接受参数:
vector(size_type,const T& value = T());
template <typename InputIterator>
vector(InputIterator first, InputIterator last);
第一个需要将5
转换为size_type
(无符号),而第二个是完美匹配,因此这将是编译器选择的那个... < / p>
...但编译器要求第二次重载,如果推断的类型InputIterator
是积分的,就好像它是一个调用:
vector(static_cast<size_type>(first),static_cast<T>(last))
C ++ 03标准有效强制要求第二个参数显式从原始类型int
转换为目标类型std::vector<int>
。由于转换是明确的,因此您会收到错误。
如果参数实际上不是输入迭代器,那么C ++ 11标准改变了使用SFINAE来禁用迭代器构造函数的措辞,因此在C ++ 11编译器中代码应该被拒绝(这可能是某些原因)声称这是一个错误。)
答案 1 :(得分:2)
对我来说,看起来它正在调用这个构造函数:
template <class InputIterator>
vector (InputIterator first, InputIterator last,
const allocator_type& alloc = allocator_type());
我不确定explicit
在哪里,因为构造函数需要多个参数。它不是从int自动转换为向量。
答案 2 :(得分:1)
这实际上是一个扩展,而不是一个错误。
被调用的构造函数是一个带有两个迭代器的构造函数(但实际上,签名将匹配同一类型的任何两个参数);然后它会调用两个迭代器实际为int
时的特化,它使用value_type
的值显式构造end
并使用begin
个副本填充向量。