【问题标题】:Implicit conversion from int to vector?从 int 到向量的隐式转换?
【发布时间】:2013-05-01 22:22:38
【问题描述】:

vector<T>有一个构造函数,它取向量的大小,据我所知是显式,这可以通过以下代码编译失败来证明 p>

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 错误(又一个)。如果有人可以详细说明答案中的错误(即总结复制它的情况),我很乐意接受它

【问题讨论】:

  • 这(正确地)不能在 GCC 4.7 上编译。又一个 MSVC++ 非标准的怪事。他们可能只是忘记标记构造函数explicit,您可以在&lt;vector&gt; 中进行检查。
  • @syam:我很高兴它无法在 GCC 上编译,但真正奇怪的是第一个示例在 MSCV 上编译,而另一个没有。这才是真正奇怪的地方
  • @ArmenTsirunyan 在 VS2012 上都不能编译;错误消息指出构造函数是explicit
  • 你为什么不看看图书馆资源?
  • @jrok:我做到了——构造函数是显式的,但代码没有被拒绝

标签: c++ visual-studio vector type-conversion explicit-constructor


【解决方案1】:

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

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

【讨论】:

  • 我不认为我理解... int 作为迭代器是什么意思?
  • @ArmenTsirunyan:std::vector 有一个构造函数,它接受一个开始和结束迭代器。它被定义为类似于template&lt;typename _It&gt; vector(_It first, _It last) 的东西,它与您的调用相匹配。然后它根据_It 的类型调用具有各种重载的函数,其中一个重载处理_Itint 的情况。
  • 回答你的问题,它不是一个迭代器,但是代码处理你给它一个int的情况。
  • 如果你说的是真的,这是我见过的最糟糕的扩展。 (不过,恐怕这有点扭曲)
  • 它并不是真正的扩展,C++03 标准需要这种行为。
【解决方案2】:

在我看来,它正在调用这个构造函数:

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

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

【讨论】:

  • 标准明确禁止在另一个构造函数也可能匹配时使用两个迭代器构造函数。
  • 我不认为我理解... int 是如何输入迭代器的?
  • InputIterator 只是模板参数 - 它可以是任何类型。
  • @MarkB 这很可能是真的——我对标准库的了解不是很广泛。我只是在说编译器似乎在做什么——而不是它应该做什么。
【解决方案3】:

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

问题是,虽然你很清楚你想要调用什么构造函数:

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(无符号),而第二个是完美匹配,所以编译器会选择这个...

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

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

C++03 标准实际上要求第二个参数显式从原始类型int 转换为目标类型std::vector&lt;int&gt;。因为转换是显式的,所以会出现错误。

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

【讨论】:

    猜你喜欢
    • 2015-09-16
    • 1970-01-01
    • 2011-05-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-07-09
    • 2020-01-04
    • 2018-11-24
    相关资源
    最近更新 更多