【发布时间】:2014-01-28 11:32:13
【问题描述】:
我有一个 C++03 应用程序,其中 std::vector<T> 类型始终用作临时缓冲区。因此,它们经常使用std::vector<T>::resize() 调整大小,以确保它们足够大以在使用前容纳所需的数据。这个函数的C++03原型其实是:
void resize(size_type n, value_type val = value_type());
所以实际上在调用resize() 时,通过添加适当数量的val 副本来扩大向量。但是,通常我只需要知道vector 足够大以容纳我需要的数据;我不需要用任何值初始化它。复制构建新值只是浪费时间。
C++11 来救援(我认为):在其规范中,它将 resize() 拆分为两个重载:
void resize(size_type n); // value initialization
void resize(size_type n, const value_type &val); // initialization via copy
这非常符合 C++ 的理念:只为您想要的东西付费。不过,正如我所指出的,我的应用程序不能使用 C++11,所以当我遇到 Boost.Container 库时我很高兴,它的文档中有 indicates support for this functionality。具体来说,boost::container::vector<T>实际上有resize()的三个重载:
void resize(size_type n); // value initialization
void resize(size_type n, default_init_t); // default initialization
void resize(size_type n, const value_type &val); // initialization via copy
为了验证我理解了一切,我做了一个快速测试来验证 C++11 std::vector<T> 和 boost::container::vector<T> 的行为:
#include <boost/container/vector.hpp>
#include <iostream>
#include <vector>
using namespace std;
namespace bc = boost::container;
template <typename VecType>
void init_vec(VecType &v)
{
// fill v with values [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
for (size_t i = 0; i < 10; ++i) v.push_back(i);
// chop off the end of v, which now should be [1, 2, 3, 4, 5], but the other 5 values
// should remain in memory
v.resize(5);
}
template <typename VecType>
void print_vec(const char *label, VecType &v)
{
cout << label << ": ";
for (size_t i = 0; i < v.size(); ++i)
{
cout << v[i] << ' ';
}
cout << endl;
}
int main()
{
// instantiate a vector of each type that we're going to test
std::vector<int> std_vec;
bc::vector<int> boost_vec;
bc::vector<int> boost_vec_default;
// fill each vector in the same way
init_vec(std_vec);
init_vec(boost_vec);
init_vec(boost_vec_default);
// now resize each vector to 10 elements in ways that *should* avoid reinitializing the new elements
std_vec.resize(10);
boost_vec.resize(10);
boost_vec_default.resize(10, bc::default_init);
// print each one out
print_vec("std", std_vec);
print_vec("boost", boost_vec);
print_vec("boost w/default", boost_vec_default);
}
在C++03模式下用g++4.8.1编译如下:
g++ vectest.cc
./a.out
产生以下输出:
std: 0 1 2 3 4 0 0 0 0 0
boost: 0 1 2 3 4 0 0 0 0 0
boost w/default: 0 1 2 3 4 5 6 7 8 9
这并不奇怪。我希望 C++03 std::vector<T> 用零初始化最后的 5 个元素。我什至可以说服自己为什么boost::container::vector<T> 会这样做(我假设它在 C++03 模式下模拟 C++03 的行为)。当我专门要求默认初始化时,我才得到了我想要的效果。但是,当我在 C++11 模式下重建时如下:
g++ vectest.cc -std=c++11
./a.out
我得到了这些结果:
std: 0 1 2 3 4 0 0 0 0 0
boost: 0 1 2 3 4 0 0 0 0 0
boost w/default: 0 1 2 3 4 5 6 7 8 9
完全一样!这导致了我的问题:
我认为在这种情况下我应该从三个测试中的每一个中看到相同的结果是不是错了?这似乎表明std::vector<T> 接口更改并没有真正产生任何影响,因为在对resize() 的最终调用中添加的5 个元素在前两种情况下仍然被初始化为零。
【问题讨论】: