std::vector构造函数的行为

3

请看下面的代码:

std::vector<std::vector<int>> v(10, 10);

这段代码在libstdc++下无法编译。然而,在使用Visual Studio的C++库时可以编译成功。我期望的行为是v被填充了10个长度为10的向量,而这正是我在使用Visual Studio时得到的结果。

使用Visual Studio调用的构造函数是接受两个迭代器的构造函数。构造函数本身定义如下:

template<class _Iter>
vector(_Iter _First, _Iter _Last)
    : _Mybase()
{   // construct from [_First, _Last)
    _Construct(_First, _Last, _Iter_cat(_First));
}

有两个版本的模板函数_Construct。它们具有相同的签名,但一个从范围初始化向量,另一个使用从第二个参数复制构造的值类型的N个副本初始化向量。在这种情况下,模板参数仅对_Construct的第二个版本有效。
结果是v被填充了10个从值10复制构造的向量的副本。通过像这样构造它,将采取相同的代码路径,正如您需要使用libstdc++实现相同效果时所做的那样:
std::vector<int> temp(10);
std::vector<std::vector<int>> v(10, temp);

哪种实现是正确的?这是libstdc++的错误还是Visual Studio的C++库的扩展?

编辑:澄清一下,我不是在问是否应该调用范围构造函数。我想知道哪个C++实现有正确的行为,无论它采取哪种方式来实现。


“10”不是迭代器,我认为VC++在这里是错误的,你只是碰巧得到了正确的结果。 - K-ballo
1
我认为这不是偶然的。被调用的_Construct函数具有签名void _Construct(_Iter _Count, _Iter _Val, _Int_iterator_tag),因此看起来它是有意的。这两个_Construct函数仅从构造函数中调用,该构造函数接受两个迭代器。 - Collin Dauphinee
2
你遇到了哪些编译错误?此外,你可能想在闭合的 > 之间添加一个空格(例如 std::vector<std::vector<int> > v(10, 10); 而不是 std::vector<std::vector<int>> v(10, 10);),以避免让编译器产生困惑。 - John Carter
错误:没有与 '__cxx1998::vector<vector<int>>::_M_fill_initialize(__cxx1998::vector<vector<int>>::size_type, int&)' 匹配的函数调用。 - Collin Dauphinee
2个回答

3
std::vector<std::vector<int>> v(10, 10);

这段代码不应该编译通过,因为vector的单参数构造函数是显式的。
C++03:
explicit vector(size_type n, const T& value = T(), const Allocator& = Allocator());

C++11:

explicit vector(size_type n);

这意味着像10这样的数字不能隐式地转换为大小为10的向量。

声明构造函数为 explicit 并不能阻止通过显式转换来构造 vector。在这种情况下,vector 是通过语句 _Ty _Newval = (_Ty)_Val 构造的;由于使用了显式转换,即使 _Val 是一个 int,它也能调用 size_t 构造函数。 - Collin Dauphinee
1
@dauphic:不过,在你达到那一点之前,你已经请求将第二个“10”隐式转换为构造函数的第二个参数。显然,模板化范围构造函数正在绕过此操作,这意味着我肯定会将其归类为错误/扩展。 - Dennis Zickefoose
好的,我知道你的意思。问题是绕过了 explicit 关键字。这很有道理,谢谢。 - Collin Dauphinee

0
我期望的行为是v被填充了10个大小为10的向量。
这正是GCC/libstdc++ 4.1.2所发生的。调用的_Construct是:
void std::_Construct<std::vector<int>, int>(std::vector<int>*, int const&)

(省略分配器)。我不能告诉你标准对此的规定,但我的直觉是这是旧版GCC/libstdc++中的一个错误。

不是,__CLIBCXX__ 被定义为 20110929。可能是新版本或者gcc/clang的bug。 - Collin Dauphinee

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接