如何在C++类中初始化变长数组?

19

我有一个类需要存储大小可变的数组。理想情况下,这个大小应该作为类构造函数的参数来定义。

我可以定义一个常量,然后使用它来完成操作,如下所示:

#include <iostream>
#define ARRSIZE 5

class Classy{
    private:
        int myarray[ARRSIZE];

    public:
        Classy();
        void printarray();
};

Classy::Classy(){
    for(int i = 0; i < ARRSIZE; i++){
        myarray[i] = i * i * 2;
    }
}

void Classy::printarray(){
    for(int i = 0; i < ARRSIZE; i++){
        std::cout << myarray[i] << std::endl;
    }
}

然而,我想这样做:

#include <iostream>
class Classy{
    private:
        int arraysize;
        int myarray[arraysize];

    public:
        Classy(int parraysize);
        void printarray();
};

Classy::Classy(int parraysize){
    arraysize = parraysize;
    for(int i = 0; i < arraysize; i++){
        myarray[i] = i * i * 2;
    }
}

void Classy::printarray(){
    for(int i = 0; i < arraysize; i++){
        std::cout << myarray[i] << std::endl;
    }
}

编译器似乎并不喜欢我的方法,所以我正在寻找另一种做事情的方式。

我在这个问题上进行了一些搜索,但是我的搜索没有取得任何成果。我发现这个方法使用动态内存分配来完成。我想避免这种情况,所以我正在寻找一种不依赖于它的解决方案。很可能(我开始思考)这是我问题的唯一优雅的解决方案(如果是这种情况,当然应该将问题关闭为重复项)。


7
请使用 std::vector - Captain Obvlious
总体而言,我不是数组的狂热爱好者,除非您真的需要它们进行一些优化,否则 std::vector 是您值得信赖的朋友,并且更有可能在满足您需求的同时灵活变通。但是您也可以使用 std::array……这是 C 数组的便捷 C++ 替代品。 - HostileFork says dont trust SE
6
@HostileFork:一个std::array不是可变大小的。std::unique_ptr <T[]>是用于在构造时设置大小的数组的标准组件。std::vector<T>用于在其生命周期内大小可以变化的数组。 - Ben Voigt
@BenVoigt 是的,我非常清楚。但是最近我参与了一次关于这个问题的讨论,有些人狂热地坚持他们想要一个数组。真是难以理解。别把信使打死。 - HostileFork says dont trust SE
@JohannesS。在你对C++更有经验之前,你真的不想学习new。先学习基础知识吧。 - user1804599
显示剩余6条评论
5个回答

18

需要使用动态分配,因为sizeof (Classy)必须是编译时常量。对象的内部大小无法增长。但动态分配并不像那个链接所建议的那样复杂。

您可以像这样做:

#include <memory>
class Classy
{
    private:
        int arraysize;
        std::unique_ptr<int[]> myarray;

    public:
        Classy(int parraysize);
        void printarray();
};

Classy::Classy(int parraysize)
    : arraysize{parraysize}
    , myarray{new int[arraysize]}
{
    for(int i = 0; i < arraysize; i++){
        myarray[i] = i * i * 2;
    }
}

#include <iostream>
void Classy::printarray()
{
    for(int i = 0; i < arraysize; i++){
        std::cout << myarray[i] << std::endl;
    }
}

这将允许大小在创建时变化,此后将被固定。std::unique_ptr将负责在对象死亡时自动销毁数组内容。


6
您希望使用模板来解决这个问题:
#include <array>

template<std::size_t ArraySize>
class Classy final
{
public:
    static const std::size_t size = ArraySize;

    /* The rest of your public interface here */
private:
    std::array<int, ArraySize> m_array;
};

然后,您可以像这样使用您的类:
int main()
{
    Classy<5> hasArrayOfFiveElements;
    return 0;
}

你完全可以选择不使用std::array,而是使用c风格的数组。但我们在编写C++代码,所以让我们使用更好的语言工具 :)


6
这不允许你按照问题要求“将尺寸传递给构造函数”。 - Ben Voigt

4

我认为在使用传统数组时无法避免使用动态内存分配,但是您可以使用std::vector。您可以这样做:

#include <iostream>
class Classy{
    private:
        int arraysize;
        std::vector<int> myArrayOfInts;

    public:
        Classy(int parraysize);
        void printarray();
};

Classy::Classy(int parraysize){
    arraysize = parraysize;
    for(int i = 0; i < arraysize; i++){
        myArrayOfInts.push_back(i * i * 2);
    }
}

void Classy::printarray(){
    for(int i = 0; i < myArrayOfInts.size(); i++){ //you could also use arraysize, but then you
        std::cout << myArrayOfInts[i] << std::endl;//must update it when you add or remove any
    }                                              // element from vector
}

std::vector需要一个类型。 - Ben Voigt
是的,当然,我忘记写了:D谢谢,我已经更新了。 - Mikołaj Mularczyk
你为什么要用 int arraysize; 来跟踪 std::vector 的大小呢?难道你不能直接使用向量的 size() 方法吗? - Galik
我尽可能地少编辑了原帖的代码,但最好还是使用size方法来完成。 - Mikołaj Mularczyk

3
您需要使用new[]动态分配您的数组,并在析构函数中使用delete[]释放它。或者,使用std::vector<int>reserve构造函数传递的数量。另一种方法是将类模板化,使用size_t参数指定要拥有的元素数量,但这完全消除了动态方面的内容(此时您可能使用std::array)。
我知道您想避免动态分配,但这是完成您想要的操作的最有效的方式(因为vector可能会占用比您预期的更多的空间)。

1
有点晚了。不过,这可能是另一种方法。
#include <iostream>
#include <cstddef>

class Classy
{
public:
    Classy();
    template <size_t ARRSIZE>
    Classy(int (&arr)[ARRSIZE], size_t size = 0);
    void printarray();
private:
    int* myarray;
    size_t max_size;
    size_t arraysize;
};

template <size_t ARRSIZE>
Classy::Classy(int (&arr)[ARRSIZE], size_t size)
{
    myarray = arr;
    max_size = ARRSIZE;
    arraysize = size;
}

void Classy::printarray(){
    for(int i = 0; i < max_size; i++){
        std::cout << i << " " << myarray[i] << std::endl;
    }
}

int main()
{
    int arr[10];
    Classy c(arr);
    
    c.printarray();

    return 0;
}

将一些固定大小的数组进行typedef,再与这种方法结合使用可能是不错的选择。 - Xofo

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接