我想为我的vector使用一个工厂函数,并且还使用迭代器而不调用resize来打破我之前的值?
是否有可能或者我错过了STL设计中的一点?
#include <vector>
#include <algorithm>
#include <iostream>
struct A
{
A():_x(42){}
A(double x):_x(x){}
double _x;
};
struct factory
{
A operator()()
{
return A(3.14);
}
};
int main()
{
std::vector<A> v;
int nbr = 3;
v.reserve(nbr);
std::generate_n(v.begin(), nbr, factory());
std::cout << "Good values" << std::endl;
for(int i = 0 ; i < nbr ; ++i)
std::cout << v[i]._x << std::endl;
v.resize(nbr); //How I can have the syntax below without the resize which blows my previous values ?
std::cout << "resize has been called so values are bad (i.e default ctor)" << std::endl;
for(std::vector<A>::iterator it = v.begin() ; it != v.end() ; ++it)
std::cout << (*it)._x << std::endl;
}
谢谢:)
答案 0 :(得分:8)
要么我不太了解你的担忧,否则你会被误导。 resize()
不会修改容器中的任何现有元素(除非您调整为较小尺寸时删除的元素除外)。
现在,您的实际问题是您的程序中存在未定义的行为。当您调用capacity() == nbr
时,该向量具有size() == 0
但generate_n
,并且该文件超出了容器的末尾。有两种解决方案,首先您可以在调用generate_n
之前调整的大小:
std::vector<A> v;
int nbr = 3;
v.resize(nbr);
std::generate_n(v.begin(), nbr, factory());
否则你可以改变迭代器的类型:
std::vector<A> v;
int nbr = 3;
v.reserve(nbr);
std::generate_n(std::back_inserter(v), nbr, factory());
答案 1 :(得分:0)
v.reserve(nbr);
std::generate_n(v.begin(), nbr, factory());
这是错误的。保留!=调整大小,保留仅在需要时分配内存。 为什么使用resize作为打印矢量?调整大小是调整大小向量的函数,开始/结束不依赖于调整大小...
答案 2 :(得分:0)
您的generate_n
未正确生成向量中的值。向量的大小为0,所以虽然它可能看起来工作正常,但是当你在向量的末尾写入时,你只是获得了运气。你确实需要使用resize
或类似的。或者(可能更高效)您可以使用back_inserter
:std::generate_n(std::back_inserter(v), nbr, factory());
答案 3 :(得分:0)
代码的第一部分已经破了。要创建向量元素,您必须调用resize
,而不是reserve
。 reserve
只能通过分配原始内存来保留未来的向量容量,但它不会创建(构造)实数向量元素。通常不允许您访问位于矢量大小和矢量容量之间的矢量元素。
您调用了reserve
,然后尝试使用您的向量,就像已经构造了元素一样:您为它们赋值并尝试读取和打印这些值。在一般情况下,这是非法的,它通常会导致未定义的行为。同时,向量的大小仍为0
,这是您尝试通过稍后对resize
的奇怪调用来补偿的。
您需要在一开始就致电resize
。从一开始就创建一个具有适当数量元素的向量。 (这也可以通过将初始大小传递给向量的构造函数来完成。)
例如,只需执行
int nbr = 3;
std::vector<A> v(nbr);
std::generate_n(v.begin(), nbr, factory());
或
std::vector<A> v;
int nbr = 3;
v.resize(nbr);
std::generate_n(v.begin(), nbr, factory());
你完成了。忘记reserve
- 在这种情况下你不需要它。