对于类中动态大小的数组,是否优先选择std::vector而不是堆数组

Is std::vector preferred over heap arrays for dynamically sized arrays in classes?

本文关键字:数组 std 选择 vector 动态 于类中 是否      更新时间:2023-10-16

如果你想让一个数组作为类的成员变量,有两个主要的选择:

A:在堆上分配内存
class X
{
    int * arr;
public:
    UnionFind(int numNodes)
    {
        arr = new int[numNodes];
    }
}
B:使用vector
class X
{
    vector <int> arr;
public:
    UnionFind(int numNodes)
    {
        arr.resize(numNodes);
    }
}

哪一个是首选的方法?我知道堆分配数组的一个缺点是你需要自己删除内存。

作为一个小问题,如果在堆上创建了X的对象,那么vector <int> arr也在对象内的堆中吗?如果是,为什么不需要手动删除vector <int> arr ?

当你在动态分配的c风格数组和std::vector<>之间做出选择时,选择vector

  • 它是安全的,是否所有的alloc/realloc/resize为您
  • 它使你的代码更灵活,可读,更容易维护
  • 在大多数用例中非常有效
  • 提供了显式迭代器和大量的成员函数,包括size()
  • 许多实现将在调试模式下进行索引检查以捕获越界错误

请注意,std::array存在于大多数c数组更可取的情况下(例如,当优先在堆栈上分配时)

您应该选择vector:

  • vectorvector元素的析构函数保证在适当的时间运行

  • .push_back这样的东西比用c++对象感知的方式编写自己的检查"容量"和调整大小/复制构造/移动代码要容易得多,使用起来也更简洁。

  • 在标准容器中应用算法更容易,使用迭代器等

  • 如果不断发展的应用程序/库需要建议,将更容易从vector移动到另一个标准容器(list, stack, map, unordered_map, deque等)

  • vector有一些有用的内务信息:size(), capacity()

  • 在c++ 11之前,与使用new[]delete[]相比,有一个性能问题——你不能预先"调整"vector的大小来容纳许多没有从原型元素复制构造它们的值的元素(这里是构造函数"2",这里是resize)——这意味着构造函数或resize必须遍历每个元素进行复制构造,即使默认构造函数是无操作的(例如故意使所有成员未初始化)

    • 这很少相关或有问题,实际上c++的行为通常更安全
  • 因为它是一个合适的类,您可以(是否应该是另一回事)重载operator<<, operator>>以方便地流式传输任意vector s

如果在堆上创建了X的对象,那么vector <int> arr是否也在该对象内的堆中?如果是,为什么不需要手动删除vector <int> arr ?

是的,vector对象本身将嵌入到X中,因此也将在堆上(类似地,它可以嵌入到自动/堆栈变量,全局/命名空间/静态变量,线程特定变量等中)。也就是说,vector对象包含一个指针,该指针跟踪vector中元素所需的任何进一步的内存,并且该内存默认情况下是动态分配的(即在堆上),而不管vector对象本身保存在哪里。

具有析构函数的成员变量(如任何vector)由其所在类的析构函数自动调用。