如何在C ++中部分初始化C结构数组?

时间:2013-07-09 21:05:51

标签: c++ c initializer-list

我遇到了问题:使用以下C ++代码(使用C样式结构),我收到以下错误:

elements of partially initialized array must have a default constructor

我认为它正在谈论不知道如何隐式初始化test.a的其余元素,但我不知道如何修复它。也许我只需要添加一个构造函数,但我不想更改结构定义(这只是我所面临的实际问题的一个简化示例)。

typedef struct inner_t
{
    const char* a;
    const int b;
    const char* c[6];
} inner;

typedef struct outer_t
{
    const inner a[10];
} outer;

int main()
{
    outer test = {{
        { "hi!", 0, { "1", "2", "3", "4", "5", ""} },
        { "", -1, { "" } }
    }};

    return 0;
}

我不关心手动初始化的元素之后会发生什么。我只关心我没有得到错误。

感谢您的帮助!

编辑:如果我向inner添加默认构造函数,如下所示:

typedef struct inner_t
{
    /* previous stuff */
    inner_t() : a(""), b(-1) { }
}

然后我得到更多错误:

initialization with '{...}' is not allowed for object of type "const inner"

我尝试添加不同的构造函数,但无济于事。我不明白的是为什么C风格的结构不只是拥有一个默认的构造函数。

4 个答案:

答案 0 :(得分:2)

首先,在C ++ 11中,这段代码应该按原样编译。 (在C中,此代码也将编译而没有任何错误。)如果出现此错误,则必须使用pre-C ++ 11 C ++编译器。

现在,关于你的声明:知道为什么你将inner::b声明为const会很有趣。为什么inner::b声明const,而不是inner::ainner::cinner::b有什么特别之处?

可以询问outer::a同样的问题。您为什么决定直接将const应用于特定成员outer::a,而不是将整个outer对象声明为const

如果这不是故意的,那么您可以停止将单个结构成员声明为const,而只需将整个test对象声明为const

typedef struct inner_t
{
    const char* a;
    int b;                       // <- removed `const` here
    const char* c[6];
} inner;

typedef struct outer_t
{
    inner a[10];                 // <- removed `const` here
} outer;

int main()
{
    const outer test = {{        // <- added `const` here
        { "hi!", 0, { "1", "2", "3", "4", "5", ""} },
        { "", -1, { "" } }
    }};

    return 0;
}

这将在前C ++ 11编译器中编译。

但是如果出于某种充分的理由它是故意的,意味着你不想改变你的声明,并且你想要将类型保持为C风格的聚合(即没有用户声明的构造函数),那么你的选择仅限于为单独声明为const的所有数据字段提供所有初始值设定项。

P.S。前C ++ 11语言规范中的措辞使原始代码非法并使我的版本合法可被视为含糊不清和/或有缺陷。这可能是GCC即使在-std=c++98模式下接受原始代码的原因,但MSVC ++拒绝它。

答案 1 :(得分:2)

如果要使用聚合初始化(这是您正在执行的操作),则不能使用任何用户定义的构造函数。它必须看起来像普通的C.见initializer_list not working in VC10

如果您删除const前面的const int b字样,那么它就可以编译好了(我在VS2008中试过了)。

我认为你要做的事情是不可能的,因为将const int b声明为结构的成员是一个C ++概念,它要求你在构造函数中初始化b,但不允许你有任何构造函数如果您使用的是aggragate初始化程序。

答案 2 :(得分:0)

首先,我想提一下,您可能需要做的就是为'inner'添加一个默认构造函数。您已经提到过您不想更改结构定义,但我认为您必须这样做。但是,我列出了另一种选择。

你的问题:

'outer'类型包含一个固定大小为10的数组,因此当初始化变量“test”时,它会尝试使用给定的数据创建10'内部。看到你没有给它足够的,它会尝试创建它们,但你没有“内部”类型的默认构造函数,因此它不知道该怎么做。

解决方案:

1)(最简单)为'inner'创建一个默认构造函数。

2)将'outer'中的“a”数组设置为动态数组,使用指针或类似std :: vector(c ++)/其他c类。

希望有所帮助。

答案 3 :(得分:0)

您不需要将const变量更改为非const,因为const变量可以初始化一次。原始代码在我的编译器(gcc 4.6.3)中使用g ++成功编译。并且它在Visual C ++中成功编译,但将文件扩展名更改为* .c。