2012-01-31 39 views
3

我试图做这样的事情:小心矢量::储备?

#include <vector> 
#include <algorithm> 

int main() 
{ 
    int l[] = {1,2,3,4}; 
    vector<int> vi(4); 
    copy(l, l+4, vi.begin()); 

    do_stuff(); 
} 

上面的代码可以编译,没有任何错误运行。然后,我把它改为这个:

int main() 
{ 
    int l[] = {1,2,3,4}; 
    vector<int> vi; 
    vi.reserve(4); //different from the above code 
    copy(l, l+4, vi.begin()); 

    do_stuff(); 
} 

根据代码,我改变vector<int> vi(4);vector<int> vi; vi.reserve(4);问题就来了,那就是改变的代码可以编译,但在运行时出现赛格故障。

根据gdb,seg-fault发生在函数do_stuff();中。

这是为什么?我做出的改变是否重要?我不能在这里使用reserve吗?

+0

你可能打算叫'vi.resize(4)',而不是'vi.reserve(4) '。但是,就像在你的第一段代码中一样,这将不必要地用四个'0'元素初始化矢量。最好'保留()'并使用'std :: back_inserter'或者立即用正确的数据初始化它。 – sbi 2012-01-31 20:11:16

回答

9

reserve()方法只分配内存,但保留它未初始化。它只影响capacity(),但size()将保持不变。

如果要创建多个实例,则应使用分配内存的resize(),并创建与传递给resize()的参数一样多的实例。

+0

但是在两者中,'vi.size()'应该在'copy(...)'之后是'4',对吧? – Alcott 2012-01-31 09:22:29

+0

@Alcott:只复制副本,不会调整矢量大小()。它只有迭代器。就好像你写了一个数组的边界。 – PlasmaHH 2012-01-31 09:24:21

+3

@Alcott:如果你不相信Als的“尺寸不会改变”,那就测试一下。 'vector vi; vi.reserve(4); std :: cout << vi.size()<<'\ n';'。它打印'0'。 – 2012-01-31 09:26:04

1

从一个特定C++ reference

在任何情况下,在通话[向量::储备]从不影响包含于载体的元素,也不是矢量的大小(对于该目的,请参阅vector::resizevector::erase ,它修改了矢量大小和内容)。

+1

请不要将这个蹩脚的错误ridden网站称为“C++文档”。人们可以认为这是官方的东西。 – PlasmaHH 2012-01-31 09:46:33

1

除了其他的答案,你不需要reservecopy,因为assign足以在这里:

int main() 
{ 
    int l[] = {1,2,3,4}; 
    vector<int> vi; 
    vi.assign(l, l + 4); 

    do_stuff(); 
} 
+3

对于这个问题,'vector'有一个带两个迭代器的构造函数。 – 2012-01-31 09:27:43

3

在我看来,你确实想达到什么是初始化向量元素列表。

std::vector<int> vi {1, 2, 3, 4}; 

如果你的编译器不支持此语法的是,你可以用好老的范围内构造:

int a[] = {1, 2, 3, 4}; 
std::vector<int> vi(a + 0, a + 4); 

这是很容易在C++ 11的新列表初始化语法实现如果由于某种原因,你真的要预留空间,然后按元素回来以后,这样写:

std::vector<int> vi; 
vi.reserve(4); 
int a[] = {1, 2, 3, 4}; 
std::copy(a + 0, a + 4, std::back_inserter(vi)); // need to #include <iterator> 
+0

全面回答,:)。顺便说一句,新的列表初始化语法'std :: vector vi = {1,2,3,4};'不会调用'vector '的copy-ctor? – Alcott 2012-01-31 13:53:41

+0

好点,我将副本列表初始化更改为直接列表初始化。但它在实践中可能没有任何区别。 – fredoverflow 2012-01-31 14:06:27

+0

如果你真的想看透OP的真实意图,你应该推荐'reserve'加'back_inserter'加'std :: iota' :-) – 2012-01-31 19:29:35