2D 矢量调整大小需要对象的默认构造函数

问题描述

我有一个简单的球类。它的初始化需要一个颜色名称

Ball::Ball(ColorName color_name) : m_color_name{color_name} {
}

我尝试创建一个二维矢量板来包含一些球。宽度和高度在外面给出。

class Board {
private:
    int m_width;
    int m_height;
    std::vector<std::vector<Ball>> m_grids;

public:
    Board(int width,int height);
    ~Board();
};

Board::Board(int width,int height) : m_width{width},m_height{height} {
    m_grids.resize(height);
    for (int row_num = 0; row_num < height; row_num ++) {
        m_grids[row_num].resize(width);
    }
}

然后编译器抱怨球类需要认构造函数来调整大小。

然后我尝试将其更改为指针。

class Board {
private:
    int m_width;
    int m_height;
    std::vector<std::vector<Ball> *> *m_grids;

public:
    Board(int width,m_height{height} {
    m_grids->resize(height);
    for (int row_num = 0; row_num < height; row_num ++) {
        m_grids->at(row_num)->resize(width);
    }
}

Board::Board(int width,m_height{height} {
    m_grids->resize(height,new std::vector<Ball>[width]);
    for (int row_num = 0; row_num < height; row_num ++) {
        m_grids->at(row_num)->resize(width);
    }
}

他们仍然抱怨同样的事情。

到目前为止,我只能为解决方法创建认构造函数

Ball::Ball() {
    m_color_name = ColorName::Default;
}

但我真的不喜欢它,因为球不应该是“default_color”。你应该像“黄色”、“粉红色”或我在别处定义的某种颜色。

有没有办法避免创建那个构造函数

解决方法

好吧,如果您不知道新空板上的球应该是什么颜色,C++ 无法帮助您。您没有为该类型提供默认构造函数,因此 C++ 无法知道要使用哪个默认值。您有多种选择。

一个。使用std::optional<ColorName>的板。在这种情况下,您将拥有一个明确的“默认”状态,即 std::nullopt。但是,您需要小心,并始终确保在需要时放置颜色。

两个。不要事先创建板。仅当您知道应该使用什么颜色时才创建它。例如。可以执行 m_grids[row_num].push_back(ColorName::Whatever);,您不需要为此使用默认构造函数。

至于指针(无论是原始的还是智能的) - 算了。在这个任务中你不需要指针。

,

与其将向量变成指针(这没有任何意义),条目本身应该是指针。由于指针可以为 nullptr,向量将可以调整大小,如下所示:

std::vector<std::vector<Ball *>> m_grids_bad;
// Or even better:
std::vector<std::vector<std::unique_ptr<Ball>>> m_grids;

// You can then assign things like this (for example):
m_grids[4][5] = std::make_unique<Ball>(ColorName::RED,5);

我强烈建议您在可能的情况下始终使用 std::unique_ptrstd::shared_ptr,因为没有任何反对意见。它可以帮助您在抛出异常时释放内存,或者允许您共享某些内存地址的所有权等。就这样做吧。

调整向量的大小现在可以像您想要的那样工作,因为 std::unique_ptr 有一个默认构造函数,它只是将其内部指针初始化为 nullptr

PS:也许我应该详细说明为什么在堆上存储向量没有意义。 Vectors已经可以将它们的内容存储在堆上,并在需要时动态重新分配内存。

另一件事:如果您的元素类型不可移动,指向指针的向量也非常有用。这在多线程情况下可能会派上用场,在这种情况下,线程有时会使用指向某事物的指针进行初始化,并依靠该指针准确地保持在内存中的位置。