数组作为数据成员

Array as a data member

本文关键字:数据成员 数组      更新时间:2023-10-16

我想要一个包含数组作为数据成员的类。数组的大小在构造期间声明。我知道数组的大小需要在编译时知道,但是有没有办法通过使用const int来定义大小并随后使用构造函数初始值设定项列表来解决此问题?我不允许使用矢量。这是我徒劳的尝试:

#include <iostream>
using namespace std;
class myArray {
    public:
        myArray(int size) : capacity(size) {}
    private:
        const int capacity;
        int a[capacity];
};
int main() {
    myArray ar(25); 
    return 0;     
}

它给出以下错误: 'capacity' was not declared in this scope

尝试改用指针

#include <iostream>
using namespace std;
class myArray {
public:
    myArray(int size) : capacity(size) {array = new int[capacity];}
    ~myArray() {delete [] array;}
private:
    const int capacity;
    int* array;
};
int main() {
    myArray ar(25); 
    return 0;     
}

并且不要忘记在析构函数中发布。

上述所有答案都是"技术上正确的",但没有一个实际上显示智能指针的使用,这使得所有额外的内存管理变得不必要。

class my_array
{
public:
   my_array (size_t sz)
     : arr {new int [sz]} {}
pirvate:
   std::unique_ptr <int[]> arr;
};

现在你不需要关心(3或5)的规则,代码是正确的,并且(大部分)异常安全。

它可以与静态常量一起使用,但您将丢失构造函数参数设置。您必须动态分配它才能使其工作:

class myArray {
    public:
        myArray(int size) : capacity(size) 
        {
            a = malloc(size * sizeof(int));
        }
        ~myArray() { free(a); }
    private:
        int capacity;
        int* a;
};
int main() {
    myArray ar(25); 
    return 0;     
}

尽管使用 new [] 分配和使用 delete [] 释放可能比 malloc 和自由更C++。

一些评论中所述,如果您动态分配并且不使用自动资源管理对象(如 shared_ptrunique_ptr ),则必须遵循三法则。

原始类的问题在于它允许将不同的值作为容量传入。因此,您无法以所需的方式使用该值创建数组。只创建一个大小为 25 的实例没有区别,这是程序的属性,并且类本身不知道它只是以这种方式使用的。


现在我不会质疑为什么你不能使用向量,但是不使用语言/库的全部功能似乎是一种耻辱。

但是,鉴于您的限制,您可以动态创建数组,而不是尝试创建固定数组:

#include <iostream>
using namespace std;
class myArray {
    public:
        myArray(int size) : capacity(size) {
            a = new int[capacity];
        }
        ~myArray() {
            delete[] a;
        }
        // Also need all those other things, mandated by the
        // rule of 3/5, to allow proper deep copy/move:
        // - copy constructor.
        // - copy assignment operator.
        // - move constructor (C++11).
        // - move assignment operator (C++11).
    private:
        const int capacity;
        int *a;
};
int main() {
    myArray ar1(25);
    myArray ar1(42);
    return 0;
}

通过将capacity作为变量传入,您有一个动态大小的数组(其大小仅在运行时已知)。这意味着编译器不知道sizeof(myArray),这将导致问题。

相反,您需要存储指向数组的指针。

另一种(丑陋的)方法是使用放置策略,将数组放在结构/类的末尾,并为其提供常量大小 1,如下所示

const性是不够的,因为你甚至可以获取用户在程序执行期间提供的值并使其const

int x;
std::cin >> x;
const int y = x;

这是不够的,因为在编译程序时必须知道数组维度。

从历史上看,如果要在声明点初始化一个static const"变量",那么这足以说服编译器它可以将该值用于数组维度:

static const unsigned int N = 5;

因为不可能出错。

如今,我们constexpr是为了使其绝对明确

您可以使用模板非类型参数(仅适用于C++)。看看这个页面和例子:

https://www.ibm.com/docs/en/zos/2.1.0?topic=arguments-template-non-type。