【问题标题】:Constructor that Dynamically allocates an array动态分配数组的构造函数
【发布时间】:2026-02-16 14:05:01
【问题描述】:

我无法掌握构造函数,特别是如何在其中动态分配数组。有人可以举一个类的例子,它有一个浮点数数组,构造函数接受一个整数 arg 并动态分配一个数组来保存这么多数字。

以及其他成员函数将如何访问该数组。

感谢您的帮助,非常感谢您提供任何其他有用的见解。

编辑:我还没有学过 std:vector,有没有更简单的方法?

【问题讨论】:

  • 编写自己的资源管理代码从来没有比使用标准库更简单。
  • vactor 更简单的方法。不使用向量更难。这就是人们不断提及它的原因。
  • 我完全同意 Mooing Duck:标准库是 C++ 的一部分。 它的存在是有原因的。学习它。用它。它让生活如此变得更加轻松。只有在对语言有了扎实的掌握后,才能进入血淋淋的实现细节。

标签: c++ arrays dynamic constructor


【解决方案1】:

这或多或少是 std::vector 所做的,尽管它的实现具有更大的通用性,所以对于新手来说阅读任何库实现的源代码有点困难(尤其是考虑到通常是噩梦般的命名约定用于标准库代码)。

这是宝宝的第一个动态数组:

class MyArray
{
  float * buf;
  std::size_t size;

public:
  explicit MyArray(std::size_t s) : buf(new float[s]), size(s) { }
  ~MyArray() { delete[] buf; }

  // Copying and reassigning is tricky! We disallow it for now.
  MyArray(MyArray const &) = delete;
  MyArray & operator=(MyArray const &) = delete;

  std::size_t size() const { return size; }
  float & operator[](std::size_t i) { return buf[i]; }
  float const & operator[](std::size_t i)  const { return buf[i]; }
};

这是异常安全的:唯一可能发生的异常是在构造函数的初始化列表中,并且只有一种情况(new)。如果发生异常,则不会泄漏任何内容,因为此时尚未分配任何其他内容。

用法:

MyArray a(20);
a[4] = 6.3;

更高级的版本将包含resize() 功能;为此,您必须分配和复制(比如说):

void resize(std::size_t n)
{
  float * tmp = new float[n];
  std::copy(buf, buf + std::min(size, n), tmp); // I assume this doesn't throw

  delete[] buf;

  buf = tmp;
  size = n;
}

一旦你理解了赋值运算符应该做什么,你就可以使用与resize() 非常相似的想法将一个MyArray 赋值给另一个。

【讨论】:

  • 我还没学过std:vector,有没有更简单的方法?
  • @Extinct23:我认为十年后,当你成为 C++ 大师时,你会回首往事,并嘲笑vector 是多么简单和美丽 :-)(真的不是复杂,只是一般。)
  • 如果没有必要的复制构造函数和复制赋值运算符,我认为显示此代码是不负责任的...(另外,return size(); 是无限递归。)
  • @Extinct23:对不起,我弄错了运算符,我的意思是它是方括号运算符。固定。
  • 我觉得这背后有一个家庭作业问题,我投票把它排除在外。
【解决方案2】:
struct Array_holder
{
    float* arr;

    Array_holder(size_t size):
    arr(new float[size])
    {}

    ~Array_holder()
    { delete[] arr; }

    float get(size_t i) const
    { return arr[i]; }
};

编写这个相当简单的代码我犯了两个粗鲁的错误:

1) 我忘了释放内存 2)如果类有析构函数,我还没有实现根据规则3需要的复制构造函数和赋值运算符。

这是一个很好的例子,说明为什么使用动态内存既复杂又危险。与以下示例进行比较:

#include <vector>

struct Array_holder
{
    std::vector<float> arr;

    Array_holder(size_t size):
    arr(size)
    {}

    float get(size_t i) const
    { return arr.at(i); }
};

这个例子更短、更简单、更易读、更不容易出错并且使用起来更可靠。

【讨论】:

  • 如果没有复制构造函数和复制赋值操作符,这个类会很快损坏内存。
【解决方案3】:

首先,因为您使用的是 C++,所以您应该只使用 std::vector

第二:

class DynamicArray {
    float* array;
public:
    DynamicArray( int size ) { array = new float[ size ]; }
    ~DynamicArray( void ) { delete[] array; }
    float* get( void ) const { return array; }
};

【讨论】:

  • 我还没学过std:vector,有没有更简单的方法?
  • 我认为std::vector 是最简单的方法,因为所有代码都是为您编写的并且已经过全面测试。
  • 如果没有复制构造函数和复制赋值操作符,这个类会很快损坏内存。
  • @ildjarn 是的,我现在明白了。好决定。这就是为什么每个人都应该只使用标准库——以避免此类错误。我想知道我是否可以删除我自己的答案,作为损害控制......