【问题标题】:Implications of T[n] vs T* style array in a class member类成员中 T[n] 与 T* 样式数组的含义
【发布时间】:2020-04-11 21:08:02
【问题描述】:

我正在为长期内存管理实现一个超级简单的容器,该容器将包含在一个数组中。

我想知道,下面这两种方法的实际含义是什么?

template<class T, size_t C>
class Container
{
public:
   T objects[C];
};

还有:

template<class T>
class Container
{
public:
  Container(size_t cap) 
  {
    this->objects = new T[cap];
  }
  ~Container() 
  {
    delete[] this->objects;
  }
  T* objects;
};

请记住,这些只是最小的示例,我没有考虑存储容量、虚拟大小等因素。

【问题讨论】:

  • 我真的会忘记这一点,因为你用 C++ 标记了这个问题。使用 std::vector 和 std::array。
  • 如果你的容器大小在编译时是已知的,选择第一个,否则选择第二个。在这两种情况下,请按照@mfnx 的建议选择std::arraystd::vector
  • 这感觉有点像essay风格的问题。可能有点宽泛。

标签: c++ memory containers


【解决方案1】:

如果容器的大小在编译时是已知的,就像第一个例子一样,你最好使用std::array。例如:

template<class T, size_t C>
class Container
{
public:
   std::array<T, C> objects;
};

这具有重要的优势:

  • 您可以通过std::get 访问其元素,它会自动检查访问是否在范围内,在编译时
  • 您有Container::objects 的迭代器,因此您可以使用algorithm library 的所有例程。

第二个例子有一些重要的缺点:

  • 在访问元素时不能强制执行边界检查:这可能会导致错误。
  • 如果构造函数中的new 抛出,会发生什么?您必须妥善处理此案。
  • 您需要合适的复制构造函数和赋值运算符。
  • 你需要一个 virtual 析构函数,除非你确定没有人从这个类派生,参见 here

您可以使用std::vector 来避免所有这些问题。

【讨论】:

  • 很好,不知道std::array,它似乎指向我正在寻找的方向。
  • 如果构造函数中的 new 抛出,则不会创建数组。您可能会遇到分配错误,但 std::vector 可能会遇到类似的错误。
【解决方案2】:

除了@francesco 的回答:

第一个例子

在您的第一个示例中,您的Container 拥有C-style array。如果在堆栈上创建了Container 的实例,则该数组也将在堆栈上。您可能想阅读heap vs stack(或类似内容)。因此,在堆栈上分配可能有优势,但您必须小心分配给数组的大小 (size_t C) 以避免堆栈溢出。

您应该考虑使用std::array&lt;T,C&gt;

第二个例子

这里你持有一个T 类型的指针,它指向你在堆上分配的C-style array(不管你是在堆栈上还是在堆上分配Container 的实例)。在这种情况下,您不需要在编译时知道大小,这在许多情况下具有明显的优势。此外,您可以为 size_t C 使用更大的值。

您应该考虑使用std::vector&lt;T&gt;

进一步研究

如需进一步研究,请阅读堆栈与堆分配/性能,std::vectorstd::array

【讨论】:

  • 这也是需要考虑的事情。那么 std::array 避免了堆栈问题?
  • 没有。栈的大小就是栈的大小。 std::array 在堆栈上分配,您不能超过堆栈大小。但是,如果你在堆上创建容器,你的 std::array 当然也会在堆上(假设你有一个容器的 std::vector,那么容器中的 std::array 成员不会给你堆栈溢出)。
猜你喜欢
  • 1970-01-01
  • 2020-11-23
  • 2011-03-04
  • 2020-06-20
  • 1970-01-01
  • 2011-08-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多