C++ 结构初始化

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/11516657/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-27 15:12:58  来源:igfitidea点击:

C++ Structure Initialization

c++

提问by Dinesh P.R.

Is it possible to initialize structs in C++ as indicated below

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

struct address {
    int street_no;
    char *street_name;
    char *city;
    char *prov;
    char *postal_code;
};
address temp_address =
    { .city = "Hamilton", .prov = "Ontario" };

The links hereand heremention that it is possible to use this style only in C. If so why is this not possible in C++? Is there any underlying technical reason why it is not implemented in C++, or is it bad practice to use this style. I like using this way of initializing because my struct is big and this style gives me clear readability of what value is assigned to which member.

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

Please share with me if there are other ways through which we can achieve the same readability.

如果有其他方法可以实现相同的可读性,请与我分享。

I have referred the following links before posting this question

在发布这个问题之前,我已经参考了以下链接

  1. C/C++ for AIX
  2. C Structure Initialization with Variable
  3. Static structure initialization with tags in C++
  4. C++11 Proper Structure Initialization
  1. 用于 AIX 的 C/C++
  2. 带有变量的 C 结构初始化
  3. C++中带有标签的静态结构初始化
  4. C++11 正确的结构初始化

采纳答案by Wyzard

If you want to make it clear what each initializer value is, just split it up on multiple lines, with a comment on each:

如果您想清楚每个初始化器的值是什么,只需将其拆分为多行,并在每行上注释:

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

回答by Gui13

After my questionresulted in no satisfying result (because C++ doesn't implement tag-based init for structures), I took the trick I found here: Are members of a C++ struct initialized to 0 by default?

我的问题没有得到令人满意的结果后(因为 C++ 没有为结构实现基于标签的初始化),我采用了我在这里找到的技巧:C++ 结构的成员是否默认初始化为 0?

For you it would amount to do that:

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

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

This is certainly the closest to what you wanted originally (zero all the fields except those you want to initialize).

这当然是最接近您最初想要的(将所有字段归零,除了要初始化的字段)。

回答by sameer chaudhari

As others have mentioned this is designated initializer.

正如其他人所提到的,这是指定的初始化程序。

This feature is part of C++20

此功能是C++20 的一部分

回答by Gene

The field identifiers are indeed C initializer syntax. In C++ just give the values in the correct order without the field names. Unfortunately this means you need to give them all (actually you can omit trailing zero-valued fields and the result will be the same):

字段标识符确实是 C 初始值设定项语法。在 C++ 中,只需按正确的顺序给出值,而无需字段名称。不幸的是,这意味着您需要全部提供(实际上您可以省略尾随零值字段,结果将相同):

address temp_address = { 0, 0, "Hamilton", "Ontario", 0 }; 

回答by Guilherme Ferreira

This feature is called designated initializers. It is an addition to the C99 standard. However, this feature was left out of the C++11. According to The C++ Programming Language, 4th edition, Section 44.3.3.2 (C Features Not Adopted by C++):

此功能称为指定初始值设定项。它是对 C99 标准的补充。然而,这个特性被排除在 C++11 之外。根据 The C++ Programming Language,第 4 版,第 44.3.3.2 节(C++ 不采用的 C 特性):

A few additions to C99 (compared with C89) were deliberately not adopted in C++:

[1] Variable-length arrays (VLAs); use vector or some form of dynamic array

[2] Designated initializers; use constructors

C99 的一些补充(与 C89 相比)在 C++ 中故意不采用:

[1] 变长数组(VLA);使用向量或某种形式的动态数组

[2] 指定的初始化器;使用构造函数

The C99 grammar has the designated initializers[See ISO/IEC 9899:2011, N1570 Committee Draft - April 12, 2011]

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

6.7.9 Initialization

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

On the other hand, the C++11 does not have the designated initializers[See ISO/IEC 14882:2011, N3690 Committee Draft - May 15, 2013]

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

8.5 Initializers

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 }
    { }

In order to achieve the same effect, use constructors or initializer lists:

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

回答by nikc

You can just initialize via ctor:

你可以通过ctor初始化:

struct address {
  address() : city("Hamilton"), prov("Ontario") {}
  int street_no;
  char *street_name;
  char *city;
  char *prov;
  char *postal_code;
};

回答by Fabian

I know this question is quite old, but I found another way of initializing, using constexpr and currying:

我知道这个问题很老了,但我找到了另一种初始化方法,使用 constexpr 和 currying:

struct mp_struct_t {
    public:
        constexpr mp_struct_t(int member1) : mp_struct_t(member1, 0, 0) {}
        constexpr mp_struct_t(int member1, int member2, int member3) : member1(member1), member2(member2), member3(member3) {}
        constexpr mp_struct_t another_member(int member) { return {member1, member,     member2}; }
        constexpr mp_struct_t yet_another_one(int member) { return {member1, member2, member}; }

    int member1, member2, member3;
};

static mp_struct_t a_struct = mp_struct_t{1}
                           .another_member(2)
                           .yet_another_one(3);

This method also works for global static variables and even constexpr ones. The only disadvantage is the bad maintainability: Everytime another member has to be made initializable using this method, all member initialization methods have to be changed.

此方法也适用于全局静态变量,甚至 constexpr 变量。唯一的缺点是可维护性差:每次必须使用此方法使另一个成员可初始化时,必须更改所有成员初始化方法。

回答by user396672

You can even pack Gui13's solution into single initialization statement:

您甚至可以将 Gui13 的解决方案打包到单个初始化语句中:

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


address ta = (ta = address(), ta.city = "Hamilton", ta.prov = "Ontario", ta);

Disclaimer: I don't recommend this style

免责声明:我不推荐这种风格

回答by run_the_race

I might be missing something here, by why not:

我可能在这里遗漏了一些东西,为什么不:

#include <cstdio>    
struct Group {
    int x;
    int y;
    const char* s;
};

int main() 
{  
  Group group {
    .x = 1, 
    .y = 2, 
    .s = "Hello it works"
  };
  printf("%d, %d, %s", group.x, group.y, group.s);
}

回答by Puppy

It's not implemented in C++. (also, char*strings? I hope not).

它不是在 C++ 中实现的。(还有,char*字符串?我希望不是)。

Usually if you have so many parameters it is a fairly serious code smell. But instead, why not simply value-initialize the struct and then assign each member?

通常,如果您有如此多的参数,则会产生相当严重的代码异味。但是,为什么不简单地对结构进行值初始化,然后分配每个成员呢?