c++ 在cpp中初始化对象后设置数组的边界

gdx19jrr  于 2023-05-20  发布在  其他
关注(0)|答案(3)|浏览(95)

我正在用C++编写一个图像渲染器,这是我从头开始编写的(除了标准库,我不想使用任何东西),但是在存储图像时遇到了一些麻烦。我用来存储图像的类看起来像这样:

class RawImage
{
    private:
        RGB pixels[][][3] = {};
    public:
        int width = 0;
        int height = 0;
        RawImage(int width, int height)
        {
            this->width = width;
            this->height = height;
        };
        RGB GetPixel(int x, int y)
        {
            if (x < 0 || x > width - 1)
                return RGB(0.f, 0.f, 0.f);
            if (y < 0 || y > height - 1)
                return RGB(0.f, 0.f, 0.f);
            return pixels[x][y];
        };
        int SetPixel(int x, int y, RGB color)
        {
            if (x < 0 || x > width - 1)
                return -1;
            if (y < 0 || y > height - 1)
                return -1;
            this->pixels[x][y] = color;
            return 0;
        }
};

当我尝试编译这段代码时,g++编译器给出以下错误:
作为多维数组的“pixels”声明必须具有除第一个维度之外的所有维度的边界。
我如何使用一个多维数组,其中第一个维度的大小不同,但第三个维度的大小是固定的?

daolsyd0

daolsyd01#

假设(正如您在注解中确认的那样)您的RGB类型是一个具有三个组件的类或结构,其构造函数的形式与您的GetPixel函数中使用的构造函数相同,那么您实际上需要一个2D数组。然而(正如在注解中提到的),通常将位图存储为大小为width × height的扁平一维数组更有效。然后可以使用公式array[y * width + x](假设行优先顺序和y坐标增加 * 向下 * 位图)对该数组中的适当元素进行索引。
你仍然有一个在编译时未知的维度的问题,所以你不能使用一个普通的数组。但std::vector container是理想的:只需在RawImage构造函数中调整它的大小,然后就可以像普通数组一样使用它。此外,当RawImage类的对象被销毁时,所使用的内存将自动释放。
下面是一个使用std::vector的类的可能实现:

#include <vector>

class RawImage {
private:
    std::vector<RGB> pixels;
public:
    int width = 0;
    int height = 0;
    RawImage(int width, int height)
    {
        this->width = width;
        this->height = height;
        pixels.resize(width * height);
    };
    RGB GetPixel(int x, int y)
    {
        if (x < 0 || x >= width )
            return RGB(0.f, 0.f, 0.f);
        if (y < 0 || y >= height)
            return RGB(0.f, 0.f, 0.f);
        return pixels[y * width + x];
    };
    int SetPixel(int x, int y, RGB color)
    {
        if (x < 0 || x >= width)
            return -1;
        if (y < 0 || y >= height)
            return -1;
        pixels[y * width + x] = color;
        return 0;
    }
};

重要提示:要像这样使用std::vector<RGB>容器,RGB类/结构必须有默认构造函数。我不知道你是如何实现这个类的,但类似下面的东西会起作用:

struct RGB {
    float r, g, b;
    RGB(float fr, float fg, float fb) : r{ fr }, g{ fg }, b{ fb } { }
    RGB() : r{ 0 }, g{ 0 }, b{ 0 } { } // Default c'tor required by std::vector
};

或者,为了简洁起见,你可以通过为每个参数提供默认值,将默认构造函数“合并”到接受三个float参数的构造函数中:

struct RGB {
    float r, g, b;
    RGB(float fr = 0, float fg = 0, float fb = 0) : r{ fr }, g{ fg }, b{ fb } { }
};
x8diyxa7

x8diyxa72#

在cpp中初始化对象后设置数组的边界
数组的大小在其生命周期中永远不会改变。它建立在创造之上。从技术上讲,这对你来说不是问题,因为你可以在构造函数中初始化数组。
但是,数组变量的大小必须是编译时常量,因此不能接受大小作为构造函数参数。
可以使用动态数组。最方便的方法是使用std::vector

uqjltbpv

uqjltbpv3#

在 C++ 中,数组并不是真正的第一大小公民,多维数组根本不是。没有办法声明一个多维数组,其中超过第一个维度不是编译时常数,句号。基本原理是普通数组是低级对象,仅用于高级容器。不幸的是,由于迭代器的工作方式,构建真正的多级容器 Package 一个多维数组(其维度仅在编译时已知)远非易事。如果你能接受的话,一个简单的方法是使用operator ()作为访问器方法:pixels(x, y),而不是pixels[x][y]

相关问题