【问题标题】:initializing array of variable size inside a class在类中初始化可变大小的数组
【发布时间】:2014-09-28 23:04:48
【问题描述】:

我正在尝试根据构造函数的输入参数初始化一个大小为 n 的数组。 这有效:

//Inside Header
class runningAverage{
    private:
        byte n;
        float array[10];
    public:
        runningAverage(byte);
};

//Inside .cpp
runningAverage::runningAverage(byte a){
    n = a;
    for (byte i = 0; i<n; i++) {
        array[i] = 0;
    }
}

这不起作用:

//Inside Header
class runningAverage{
    private:
        byte n;
        float array[];
    public:
        runningAverage(byte);
};

//Inside .cpp
runningAverage::runningAverage(byte a){
    n = a;
    for (byte i = 0; i<n; i++) {
        array[i] = 0;
    }
}

我想将数组初始化为 n 指定的大小。这样我就不会通过任意指定 float array[256] 或类似的东西来浪费内存。任何帮助表示赞赏!

【问题讨论】:

  • 另外值得注意的是,这是为 arduino 库编写的!
  • 对于初始化数组,您需要传递一些值。所以当你从用户那里收到 n 的值时,你需要传递它。
  • 阅读 C++ 中的指针和 newdelete,这将允许您创建所需大小的数组
  • 我知道这些事情,但我不明白它们之间的关系。你能给我写个例子吗?

标签: c++ arrays class arduino initialization


【解决方案1】:

你必须实际分配数组;你会想要使用指针类型,float array[] 不是你想的那样。正如 juanchopanza 提醒我们的那样,您还需要禁用复制构造函数和赋值运算符,或者实现进行适当深度复制的那些。

//Inside Header
class runningAverage{
    private:
        byte n;
        float *array; // <= correct type
    public:
        runningAverage(byte);
        ~runningAverage(); // <= you'll need a destructor to cleanup
    private:
        runningAverage(const runningAverage &);
        runningAverage & operator = (const runningAverage &);
};

//Inside .cpp
runningAverage::runningAverage(byte a){
    array = new float[n]; // <= allocate array
    n = a;
    for (byte i = 0; i<n; i++) {
        array[i] = 0;
    }
}

// clean up
runningAverage::~runningAverage(){
    delete[] array;
}

但是,如果您有一些动态的、自动的容器供您使用(例如 std::vector),您可能希望使用它来代替 - 那么您不必处理复制/分配/析构函数/内存管理。

【讨论】:

  • 最好还提供复制和赋值运算符,或者禁用这些操作。
  • 哇,谢谢这解决了我的问题。只是几个问题。如果它永远不会被调用,你真的需要一个析构函数吗?让我直截了当地说,数组被声明为指向浮点数的指针。那么在 new float[n] 处,您正在为数组分配内存吗?还有为什么删除后还有方括号?
  • 什么是复制和赋值运算符? @juanchopanza
  • 顺便说一句,您不需要构造函数中的循环,您可以像这样对数组元素进行零初始化:array = new float[n]();
  • @user3912409 "c++ copy constructor and assignment operator"。您应该养成在需要特殊清理时始终定义析构函数的习惯,原因有十几个。
【解决方案2】:

如果你只知道运行时的大小,Jason C 的答案就是你想要的。 (与 juanchopanzas 评论)

如果在编译时知道大小,可以使用模板:

template < int SIZE >
class runningAverage
{
    float array [ SIZE ];
};

runningAverage < 10 > ra;

或者使用std::array 之类的类来代替std::vector

【讨论】:

  • 使用这种方法比 Jason 的方法有优势吗?我对模板没有任何经验....
  • @user3912409 有优点也有缺点,这个话题在很多其他地方都有讨论,这里有点多。
  • 在某些情况下,杰森的答案更合适,在某些情况下是我的。与您的需求无关的唯一优势是,我的方法不需要您处理复制/赋值运算符。但是,如果您只使用std::vector,这个问题也会为您解决。每种方法的所有其他(缺点)优点取决于您实际使用此代码的目的,因此我无法在这里回答。
  • 哦,是的,我忘了:我的代码的一个缺点就像我在回答中所说的那样,您需要在编译时知道大小。
【解决方案3】:
  1. 您的成员应该是一个指针,以便在构造对象时可以进行动态内存分配:float *array;
  2. 在构造函数中,使用array = new float[a];
  3. 在构造函数中,最好使用memset 而不是循环进行初始化。
  4. 有一个析构函数来释放内存,这行:delete[] array;
  5. 要让它编译,你需要这一行:#include &lt;new&gt;
  6. 要链接,不要忘记在使用g++时包含链接器标志-lstdc++

由于您似乎是初学者,请查看此有用的参考资料:http://www.cplusplus.com/doc/tutorial/dynamic/

【讨论】:

  • 我经常看到编译器将这样的循环和 memset 简化为相同的东西。
  • @JasonC Ant 将数组初始化为零的惯用方法既不是循环也不是memset,而是array = new float[a]();
  • 那很好。我已经很多年没有用 C++ 编写过了。好刷新。
  • 此外,您不需要为此包含 &lt;new&gt;(除非您想使用 std::bad_allocstd::nothrow),而 g++ 隐式链接到 libstdc++ .
  • 你提供的那个来源对我帮助很大。非常感谢。
猜你喜欢
  • 2023-02-23
  • 2014-11-29
  • 2021-06-08
  • 1970-01-01
  • 1970-01-01
  • 2021-07-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多