矢量预分配不能正常工作

Vector preallocation does not work properly

本文关键字:工作 常工作 预分配 不能      更新时间:2023-10-16

我有一些问题与以下代码:

#include <iostream>
#incldue <vector>
template <typename ElemType>
class A{
private:
  std::vector<ElemType> data;
public:
  A() {};
  A(int capacity) {
    data.reserve(capacity);
  }
  int GetCapacity() {
    return data.capacity();
  }
};
int main() {
  A<int> a;
  a = A<int>(5);
  std::cout << a.GetCapacity() << std::endl; 
} 

输出为0。有什么问题吗?

std::vector<T>的复制构造函数和赋值操作符不需要复制vector的容量,只需要复制元素。因为a = A<int>(5)行间接调用了赋值操作符(在创建临时容器之后),所以a中的vector没有容量。

尝试将main的前两行更改为A<int> a(5),看看结果如何。

如果您绝对需要将容量从一个实例转移到另一个实例的能力,则需要定义A的赋值和复制构造函数来复制数据和分配容量。

因为您没有实现A的复制赋值,从而保留了vector的容量。编译器生成的A的复制赋值确保只复制vector的元素。不需要vector的复制构造函数(和复制赋值)来保留源vector对象的容量。它复制元素,保留vector的size

这意味着,如果您将A的复制赋值定义为:
 A& operator = (const A & a) 
 {
    data = a.data;
 }

仍然会打印0

您想要的行为可以通过实现复制赋值来实现:

 A& operator = (const A & a) 
 {
    data.reserve(a.capacity());
    data.insert(data.end(), a.begin(), a.end());
 }

注意.insert()只复制元素,因为.size()改变了,但.capacity保持不变。这就是为什么需要显式调用.reserve()

这是因为你给a赋值,赋值只会复制值和容量。

如果你想构造一个固定的容量,那么

A<int> a(5);

如果你想用赋值来转移容量,你需要自己编写赋值操作符

A& operator=(const A& a)
{
     if(&a!=this)
     {
         data.assign(a.data);
         data.reserve(a.capacity);
     }
     return *this; 
}