是否可以在c++中初始化结构,如下所示:

struct address {
    int street_no;
    char *street_name;
    char *city;
    char *prov;
    char *postal_code;
};

address temp_address = { .city = "Hamilton", .prov = "Ontario" };

这里和这里的链接提到,这种样式只能在C中使用。如果是这样,为什么在c++中不能使用呢?是否有任何潜在的技术原因,为什么它不是在c++中实现的,或者使用这种风格是不好的做法。我喜欢使用这种初始化方式,因为我的结构体很大,而且这种样式可以让我清楚地了解分配给哪个成员的值。

请与我分享是否有其他方法可以达到同样的可读性。

在提出这个问题之前,我已参考以下连结:

C/ c++ for AIX C结构初始化变量 c++中使用标记的静态结构初始化 c++ 11正确的结构初始化


当前回答

这个特性称为指定初始化式。它是C99标准的补充。然而,这个特性在c++ 11中被忽略了。根据c++编程语言,第4版,第44.3.3.2节(c++未采用的C特性):

c++故意没有采用C99的一些附加功能(与C89相比): [1]变长数组(VLAs);使用矢量或某种形式的动态数组 [2]指定初始化式;使用构造函数

C99语法有指定的初始化式[参见ISO/IEC 9899:2011, N1570委员会草案- 2011年4月12日]

6.7.9初始化

initializer:
    assignment-expression
    { initializer-list }
    { initializer-list , }
initializer-list:
    designation_opt initializer
    initializer-list , designationopt initializer
designation:
    designator-list =
designator-list:
    designator
    designator-list designator
designator:
    [ constant-expression ]
    . identifier

另一方面,c++ 11没有指定的初始化式[参见ISO/IEC 14882:2011, N3690委员会草案- 2013年5月15日]

8.5初始化

initializer:
    brace-or-equal-initializer
    ( expression-list )
brace-or-equal-initializer:
    = initializer-clause
    braced-init-list
initializer-clause:
    assignment-expression
    braced-init-list
initializer-list:
    initializer-clause ...opt
    initializer-list , initializer-clause ...opt
braced-init-list:
    { initializer-list ,opt }
    { }

为了达到同样的效果,可以使用构造函数或初始化列表:

其他回答

我今天遇到了一个类似的问题,我有一个结构体,我想用测试数据填充,这些数据将作为参数传递给我正在测试的函数。我想有这些结构的一个向量,并正在寻找一个单行方法来初始化每个结构。

我最终在struct中使用了一个构造函数,我相信在对您的问题的一些回答中也建议了这一点。

让构造函数的实参与公共成员变量具有相同的名称可能是不好的做法,这需要使用this指针。如果有更好的方法,有人可以建议编辑。

typedef struct testdatum_s {
    public:
    std::string argument1;
    std::string argument2;
    std::string argument3;
    std::string argument4;
    int count;

    testdatum_s (
        std::string argument1,
        std::string argument2,
        std::string argument3,
        std::string argument4,
        int count)
    {
        this->rotation = argument1;
        this->tstamp = argument2;
        this->auth = argument3;
        this->answer = argument4;
        this->count = count;
    }

} testdatum;

我在我的测试函数中使用它来调用被测试的函数,使用各种参数,像这样:

std::vector<testdatum> testdata;

testdata.push_back(testdatum("val11", "val12", "val13", "val14", 5));
testdata.push_back(testdatum("val21", "val22", "val23", "val24", 1));
testdata.push_back(testdatum("val31", "val32", "val33", "val34", 7));

for (std::vector<testdatum>::iterator i = testdata.begin(); i != testdata.end(); ++i) {
    function_in_test(i->argument1, i->argument2, i->argument3, i->argument4m i->count);
}

在gnuc++中(似乎从2.5开始就过时了,很久以前了:)看到答案在这里:使用标签初始化C结构。它可以工作,但如何?),可以像这样初始化一个结构体:

struct inventory_item {
    int bananas;
    int apples;
    int pineapples;
};

inventory_item first_item = {
    bananas: 2,
    apples: 49,
    pineapples: 4
};

这是可能的,但前提是初始化的结构体是POD(普通旧数据)结构体。它不能包含任何方法、构造函数,甚至默认值。

在我的问题没有得到令人满意的结果之后(因为c++没有为结构实现基于标记的init),我使用了我在这里找到的技巧:c++结构体的成员默认初始化为0吗?

对你来说,它相当于这样做:

address temp_address = {}; // will zero all fields in C++
temp_address.city = "Hamilton";
temp_address.prov = "Ontario";

这当然是最接近您最初想要的(除那些您想初始化的字段外,所有字段都为零)。

如果你想清楚每个初始化值是什么,只需要把它分成多行,并在每一行上加一个注释:

address temp_addres = {
  0,  // street_no
  nullptr,  // street_name
  "Hamilton",  // city
  "Ontario",  // prov
  nullptr,  // postal_code
};