初始化C++向量的大小

amh*_*ies 13 c++

初始化C++向量以及其他容器的大小有什么好处(如果有的话)?有没有理由不只使用默认的no-arg构造函数?

基本上,两者之间是否存在显着的性能差异

vector<Entry> phone_book;
Run Code Online (Sandbox Code Playgroud)

vector<Entry> phone_book(1000);
Run Code Online (Sandbox Code Playgroud)

这些例子来自Bjarne Stroustrup的C++编程语言第三版.如果这些容器应该总是用一个尺寸进行初始化,那么有一个很好的方法可以确定一个好的尺寸开始吗?

bol*_*lov 35

有三种创建vectorwith n元素的方法:

(一个):

std::vector<Entry> phone_book;
for (std::size_t i = 0; i < n; ++i) {
    phone_book.push_back(entry);
}
Run Code Online (Sandbox Code Playgroud)

(B):

std::vector<Entry> phone_book(n);
for (auto& elem : phone_book) {
    elem = entry;
}
Run Code Online (Sandbox Code Playgroud)

(C):

std::vector<Entry> phone_book(n, entry);
Run Code Online (Sandbox Code Playgroud)

(A)的缺点是当你推回元素时会发生重新分配.这意味着内存分配,元素移动(或者如果它们不可移动则复制,或者用于预先c ++ 11)和内存释放(具有对象销毁).对于一个push_back相当大的人来说,这很可能不止一次发生.

(B)不会产生任何重新分配,但所有n元素最初都是默认构造的,然后为每次推送复制.这是一个很大的缺点,对性能的影响是可以衡量的.(对于基本类型,这不太明显)

(C)是最好的使用方法.不会发生重新分配,对象只会构造一次.push_back可以选择更好的选择push_back.


如果您不知道高级尺寸,您可以做的是(A).

如果你只是粗略地使用了大小(C)(更喜欢更大的猜测而不是更低的猜测),最后你可以使用shrink_to_fit.

  • 值得一提的是vector&lt;Entry&gt;phone_book(n); 在 c++11 之前和 c++11 之后具有不同的行为。直到c++11,都会构造一个Entry实例,然后复制n次。在c++11之后,将创建n个Entry实例。这是一条至关重要的信息,因为当使用指针类时,它也会初始化对象(可能用 new ),即 vector&lt;Entry&gt;phone_book(n); 直到 c++11 实际上将地址复制 n 次,本质上指向同一个对象。 (3认同)

sfj*_*jac 10

如果你事先知道大小是多少,那么你应该初始化它,以便只分配一次内存.如果您只是大致了解大小,那么您可以使用默认构造函数创建向量,然后保留大致正确的数量,而不是像上面那样分配存储.例如

vector<Entry> phone_book();
phone_book.reserve(1000);

// add entries dynamically at another point

phone_book.push_back(an_entry);
Run Code Online (Sandbox Code Playgroud)

编辑:

@juanchopanza提出了一个很好的观点 - 如果你想避免默认构造对象,那么push_back如果你有一个移动构造函数或者emplace_back直接构造就可以保留并使用它.