【问题标题】:Passing an initialization list to an array member in C++将初始化列表传递给 C++ 中的数组成员
【发布时间】:2020-02-03 00:49:59
【问题描述】:

使用聚合类时,传入数组成员的初始化列表不是问题。例如:

class color_def
{
 public:
    const u8 color_passes;
    const u8 red_shift[MAX_COLOR_PASSES];
    const u8 red_bitcount[MAX_COLOR_PASSES];
    const u8 green_shift[MAX_COLOR_PASSES];
    const u8 green_bitcount[MAX_COLOR_PASSES];
    const u8 blue_shift[MAX_COLOR_PASSES];
    const u8 blue_bitcount[MAX_COLOR_PASSES];
};

const static color_def snk_neogeo_color = {
        3, {15, 14, 8}, {1, 1, 4}, {15, 13, 4}, {1, 1, 4}, {15, 12, 0}, {1, 1, 4}};

这没有任何问题。但是,当我添加显式构造函数时,它将不起作用。例如,来自类似的类:

class chr_def
{
 public:
    chr_def(u16 width, u16 height, u8 bitplanes, u32 planeoffset[MAX_GFX_PLANES],
                    u32 xoffset[MAX_GFX_SIZE], u32 yoffset[MAX_GFX_SIZE],
                    const u8 *(*converter)(const chr_def *chrdef, const u8 *data))
            : width(width),
                height(height),
                bitplanes(bitplanes),
                planeoffset{planeoffset},
                xoffset(xoffset),
                yoffset(yoffset),
                converter(converter),
                datasize(width * height * bitplanes){};

    const u8 *convert(const u8 *data) { return this->converter(this, data); }

    const u16 width;                 // pixel width of each element
    const u16 height;                // pixel height of each element
    const u8 bitplanes;          // number of color bitplanes
    const u32 *planeoffset; // bit offset of each bitplane
    const u32 *xoffset;          // bit offset of each horizontal pixel
    const u32 *yoffset;          // bit offset of each vertical pixel
    const u32 datasize;          // size of one chr in bits
    const u8 *(*converter)(const chr_def *, const u8 *);
};

const static chr_def nintendo_sfc = {
        8,
        8,
        4,
        {0, 8, 128, 136},
        {0, 1, 2, 3, 4, 5, 6, 7},
        {0 * 16, 1 * 16, 2 * 16, 3 * 16, 4 * 16, 5 * 16, 6 * 16, 7 * 16},
        get_chr};

失败,抱怨参数与构造函数不匹配。问题似乎是它将数组初始化列表的第一个值作为指向数组的指针:

note: candidate constructor not viable: cannot convert initializer list argument to 'u32 *' (aka 'unsigned int *')

如果我将数组初始化列表拉出并预先将它们初始化为自己的变量,如下所示:

u32 temp1[4] = {0, 8, 128, 136};
u32 temp2[8] = {0, 1, 2, 3, 4, 5, 6, 7};
u32 temp3[8] = {0 * 16, 1 * 16, 2 * 16, 3 * 16, 4 * 16, 5 * 16, 6 * 16, 7 * 16};
const static chr_def nintendo_sfc = {
        8,
        8,
        4,
        temp1,
        temp2,
        temp3,
        get_chr};

一切正常。如果可能的话,我真的更希望这样做。

那么...为什么这在聚合形式中有效,但不适用于我的显式构造函数?有什么办法可以使这项工作?感谢任何人可以提供的任何见解。

【问题讨论】:

  • 数组大小是否依赖于width/height/bitplanes?如果是这样,您应该考虑将它们设为模板参数。
  • 指针是单个值。用多个值初始化它是没有意义的。使用指针初始化指针(在有效的示例中,数组衰减为指针)。您是否考虑过使用 std::array 代替哑数组?

标签: c++ arrays constructor initializer-list


【解决方案1】:

给你带来麻烦的不是显式构造函数,而是你使用的指针而不是数组:

以下变量声明:

const u8 red_shift[MAX_COLOR_PASSES];
const u8 red_bitcount[MAX_COLOR_PASSES];
const u8 green_shift[MAX_COLOR_PASSES];
const u8 green_bitcount[MAX_COLOR_PASSES];
const u8 blue_shift[MAX_COLOR_PASSES];
const u8 blue_bitcount[MAX_COLOR_PASSES];

变成:

const u32 *planeoffset;      // bit offset of each bitplane
const u32 *xoffset;          // bit offset of each horizontal pixel
const u32 *yoffset;          // bit offset of each vertical pixel

指针与数组不同。

您可以阅读它们之间的区别:Is an array name a pointer?

要启用这些指针,您必须在构造函数中接收接受 initializer_list 的类型,然后在函数内部为指针分配新的内存位置,然后将数组中的值复制到新分配的指针。

【讨论】:

  • 这就是我最初的方式,它给了我一个不同的错误:inc/global.hpp:48:5: error: array initializer must be an initializer list planeoffset(planeoffset), The only它的编译方式是使用变量作为指针......
【解决方案2】:

您遇到的问题是您试图用std::initializer_list 初始化指针成员,这根本不可能。

但是,您可以使用std::array(c++ 11 起)。这是一个简化的例子:

#include <iostream>
#include <array>

#define MAX_GFX_PLANES (4U)

struct chr_def {
    // Constructor
    chr_def(size_t size, const std::array<unsigned int, MAX_GFX_PLANES>& planeoffset) :
        size(size), planeoffset(planeoffset) { };

    // Data Members
    const size_t size;
    const std::array<unsigned int, MAX_GFX_PLANES> planeoffset;
};

const static chr_def nintendo_sfc{ 8U, {0U, 1U, 2U, 3U} };

int main() {
    // std::array can be used with range-based for
    for (auto i : nintendo_sfc.planeoffset) {
        std::cout << i << " ";
    }
    return 0;
}

【讨论】:

  • 我知道 cmets 并不是真的要说谢谢,但是...谢谢!完美无瑕!
猜你喜欢
  • 2015-02-07
  • 2015-08-03
  • 2011-12-01
  • 1970-01-01
  • 2015-11-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-12-19
相关资源
最近更新 更多