使用push_back分配内存与构造特定大小的向量

时间:2018-07-13 03:19:16

标签: c++ performance vector

在C ++ Primer中发现以下语句

  

由于向量有效增长,因此通常是不必要的,并且可以   导致性能较差-定义特定大小的向量。   此规则的例外情况是,如果所有元素实际上都需要   相同的值。如果需要不同的元素值,通常会更大   定义空向量并将元素添加为值的效率很高   需要在运行时知道。

我对此有疑问,如果您事先保留了内存,那么就不需要重新分配(这被认为是一个较慢的过程)。那么如何使用push_back带来更好的性能呢?

4 个答案:

答案 0 :(得分:4)

我认为作者正在比较以下两种情况:

int n = ...;
std::vector<...> v(n);
for (auto& x : v) x = some_value_known_at_runtime;

int n = ...;
std::vector<...> v;
for (int i = 0; i < n; i++) v.push_back(some_value_known_at_runtime);

第一种情况是使用vector默认构造的元素构造n,然后再分配它们;这可能会导致性能下降。

当然,您可以在第二种情况下使用reserve,这样可以避免重新分配并提高效率;如果可以提前知道元素的数量。

int n = ...;
std::vector<...> v;
v.reserve(n);
for (int i = 0; i < n; i++) v.push_back(some_value_known_at_runtime);

答案 1 :(得分:1)

这取决于您在默认构造函数中所做的工作。如果您的对象在默认构造函数中做一些昂贵的事情,则您的程序可以在向量分配中冻结一会儿。相反,push_back将为每个对象一次并递增(或及时)调用副本构造函数。那可能更快。

但是,重新分配和批量复制可能也很昂贵,特别是如果您的对象是许多对象的组合,依此类推,那么在这种情况下,只有概要分析可以说出最好的方法。

另一方面,如果默认构造函数不执行任何操作,则在大多数情况下避免重新分配将是胜利。

答案 2 :(得分:1)

我在C ++入门中看到了这一说法,他在以下情况中如此说道。

// read words from the standard input and store them as elements in a vector 
string word;
vector<string> text; // empty vector
while (cin >> word) {
    text.push_back(word); // append word to text 
}

这里的向量每次都以不同的值增长大小。

他还说的是“经常不必要”而不是“总是”。我对它进行了已知次数的测试,并且在所有情况下储备金的表现都更好。

请参阅下面的Vector实现代码片段,以便更好地理解。

template<typename T> 
class Vector {
    T∗ elem;  // pointer to first element
    T∗ space; // pointer to first unused (and uninitialized) slot 
    T∗ last;  // pointer to last slot
public: 
    // …
    int size();      // number of elements (space-elem)
    int capacity();  // number of slots available for elements (last-elem)
    // ...
    void reserve(int newsz); // increase capacity() to newsz
    // ...
   void push_back(const T& t); // copy t into Vector
};

template<typename T>
void Vector<T>::push_back(const T& t) { 
    if (capacity()<size()+1)            // make sure we have space for t 
        reserve(size()==0?8:2∗size());  // double the capacity 
    new(space){t};                      // initialize *space to t 
    ++space; 
} 

答案 3 :(得分:0)

没有什么要考虑的。

您是否经常使用一个和相同的向量,我的意思不是5或10次,而是数千次。原因是您想尽可能地重用该对象,以避免不必要的分配和释放。为此,您可以使用clear

向量有可能总是具有一定数量的元素,那么您可以使用reserve命令预分配元素。

通常,如果您将向量作为永久存储,而很少更改内容,则不要理会这些内容。