初始化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.
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直接构造就可以保留并使用它.