C ++结构初始化

问题描述 投票:257回答:17

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

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

链接herehere提到只能在C中使用这种样式。如果是这样,为什么在C ++中不能使用这种样式?是否有任何根本的技术原因导致无法在C ++中实现,还是使用这种样式的错误做法?我喜欢使用这种初始化方式,因为我的结构很大,并且这种样式使我清楚地知道了将哪个值分配给哪个成员。

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

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

  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
c++
17个回答
151
投票
address temp_addres = { 0, // street_no nullptr, // street_name "Hamilton", // city "Ontario", // prov nullptr, // postal_code };

4
投票
#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); }

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

然后声明从原始结构类型继承的新类型的变量,并将构造函数用于字段初始化:

struct temp_address : address { temp_address() { 
    city = "Hamilton"; 
    prov = "Ontario"; 
} } temp_address;

虽然不如C风格那么优雅...

对于局部变量,它在构造函数的开头需要一个附加的memset(this,0,sizeof(* this)),因此显然它并不差,并且@ gui13的答案更合适。

((请注意,'temp_address'是'temp_address'类型的变量,但是,此新类型继承自'address',并且可以在所有需要'address'的地方使用,所以可以。)


1
投票

1
投票
这是一个好习惯,但是有时像您的示例一样,预先初始化很方便。 OOP通过抽象类或creational design patterns解决此问题。

我认为,使用这种安全方式会破坏简单性,有时安全性折衷可能太昂贵,因为简单的代码不需要复杂的设计即可保持可维护性。

作为一种替代解决方案,我建议使用lambda定义宏以简化初始化,使其看起来几乎像C样式:

struct address { int street_no; const char *street_name; const char *city; const char *prov; const char *postal_code; }; #define ADDRESS_OPEN [] { address _={}; #define ADDRESS_CLOSE ; return _; }() #define ADDRESS(x) ADDRESS_OPEN x ADDRESS_CLOSE

ADDRESS宏扩展到

[] { address _={}; /* definition... */ ; return _; }()

创建并调用lambda。宏参数也是逗号分隔的,因此您需要将初始化程序放在方括号中,然后像

那样调用
address temp_address = ADDRESS(( _.city = "Hamilton", _.prov = "Ontario" ));

您还可以编写通用宏初始化程序

#define INIT_OPEN(type) [] { type _={};
#define INIT_CLOSE ; return _; }()
#define INIT(type,x) INIT_OPEN(type) x INIT_CLOSE

但随后通话效果不太好

address temp_address = INIT(address,( _.city = "Hamilton", _.prov = "Ontario" ));

但是您可以使用常规的INIT宏轻松定义ADDRESS宏

#define ADDRESS(x) INIT(address,x)

1
投票

0
投票

0
投票

-15
投票

94
投票
对您而言,这样做:

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

这肯定是最接近您最初想要的内容(将所有要初始化的字段都清零)。


15
投票
address temp_address = { 0, 0, "Hamilton", "Ontario", 0 };

15
投票
此功能是C++20的一部分

12
投票
指定的初始值设定项。它是C99标准的补充。但是,此功能不在C ++ 11中。根据C ++编程语言,第4版,第44.3.3.2节(C ++不采用的C功能):

[C99故意添加了一些C99(与C89相比):

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

[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 } { } 为了达到相同的效果,请使用构造函数或初始化列表:


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

7
投票
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);

免责声明:我不推荐这种样式


7
投票
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);

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


5
投票
通常,如果您有太多参数,这是相当严重的代码味道。但是,为什么不简单地对结构进行值初始化然后分配每个成员呢?
© www.soinside.com 2019 - 2024. All rights reserved.