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++ 实现具有正确的行为,无论它采用哪条路径来实现它。

4

2 回答 2

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

这不应该编译,因为向量的单参数构造函数是显式的。

C++03:

explicit vector(size_type n, const T& value = T(), const Allocator& = Allocator());

C++11:

explicit vector(size_type n);

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

于 2011-10-08T23:18:18.730 回答
0

我期望的行为是 v 填充了 10 个大小为 10 的向量

这正是 GCC/libstdc++ 4.1.2 发生的事情。所谓的_Construct

void std::_Construct<std::vector<int>, int>(std::vector<int>*, int const&)

(省略分配器)。我无法告诉您标准对此有何规定,但我的直觉是,这是旧 GCC/libstdc++ 中的一个错误。

于 2011-10-08T22:21:00.983 回答