8

vector<T>有一个构造函数,它采用向量的大小,据我所知它是显式的,这可以通过以下代码无法编译的事实来证明

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


好的,似乎这是一个 MSVC 错误(又一个)。如果有人可以详细说明答案中的错误(即总结复制它的情况),我很乐意接受

4

3 回答 3

7

这不是一个真正的错误。问题是在第一段代码无法编译的情况下允许第二段代码会出现什么问题?

问题是,虽然在您这样做时要调用什么构造函数对您来说似乎很明显:

std::vector<std::vector<int>> graph(5, 5);

对于编译器来说还不是很清楚。特别是有两个可以接受参数的构造函数重载:

vector(size_type,const T& value = T());

template <typename InputIterator>
vector(InputIterator first, InputIterator last);

第一个需要转换5size_type(无符号),而第二个是完美匹配,所以这将是编译器选择的那个......

...但是编译器要求第二个重载,如果推导的类型InputIterator是整数,则其行为就像是对以下内容的调用:

vector(static_cast<size_type>(first),static_cast<T>(last))

C++03 标准有效地要求第二个参数从原始类型显式int转换为目标类型std::vector<int>。因为转换是显式的,所以您会收到错误。

如果参数不是真正的输入迭代器,C++11 标准更改了措辞以使用 SFINAE 禁用迭代器构造函数,因此在 C++11 编译器中代码应该被拒绝(这可能是一些人声称这一点的原因成为一个错误)。

于 2013-05-07T20:55:54.633 回答
2

对我来说,它看起来像是在调用这个构造函数:

template <class InputIterator>
vector (InputIterator first, InputIterator last,
  const allocator_type& alloc = allocator_type());

我不确定explicit它的来源,因为构造函数需要多个参数。它不是从 int 自动转换为向量。

于 2013-05-07T20:43:17.363 回答
1

这实际上是一个扩展,而不是一个错误。

被调用的构造函数是带有两个迭代器的构造函数(但实际上,签名将匹配任何两个相同类型的参数);当两个迭代器实际为 时,它调用一个特化,它使用 的值int显式构造 a并用它的副本填充向量。value_typeendbegin

于 2013-05-07T20:42:28.490 回答