在结构中初始化默认值


73

如果我只需要初始化C ++结构的几个选择值,这是否正确:

struct foo {
    foo() : a(true), b(true) {}
    bool a;
    bool b;
    bool c;
 } bar;

我是否正确地假设我最终会得到一个struct名为bar元素的项bar.a = truebar.b = true而未定义项bar.c呢?


该酒吧只是一个重命名,如果您使用的是c ++,则无需采用这种方式
aaronman 2013年

12
@aaronman不,bar是变量。
Luchian Grigore

5
@aaronman我认为您将与此混淆typedef struct foo {} bar;
greatwolf

1
那么,如果bar是该结构,那是foo什么?这与定义foo结构并分别将新变量声明bar为类型foo是否相同?
文斯

2
bar只是一个foo对象。它与struct foo {//something}; foo bar;
Yan Yi

Answers:


39

是。bar.a并且bar.b设置为true,但bar.c未定义。但是,某些编译器会将其设置为false。

在此处查看实时示例:struct demo

根据C ++标准8.5.12节:

如果不执行初始化,则具有自动或动态存储持续时间的对象的值不确定

对于原始的内置数据类型(bool,char,wchar_t,short,int,long,float,double,long double),如果未明确初始化,则仅全局变量(所有静态存储变量)的默认值为零。

如果您真的不希望undefinedbar.c开头,则还应该像对bar.aand一样进行初始化bar.b


1
@CaptainObvlious刚刚更新,对不起,我被其他东西分散了注意力,而不是与计算机无关。
taocp

4
它不是“未定义”的,它是未初始化的,意味着它具有不确定的值
乔纳森·威克利

我认为OP的意思是说是不确定的,而不是成员。
srujzs

236

您甚至不需要定义构造函数

struct foo {
    bool a = true;
    bool b = true;
    bool c;
 } bar;

需要说明的是:这些被称为大括号或相等初始化器(因为您也可以使用大括号初始化而不是等号)。这不仅适用于集合:您可以在普通的类定义中使用它。这是在C ++ 11中添加的。


116
下注者:在向人们讲解什么是合法的或不合法的之前,请使自己熟悉对标准的C ++ 11更新。 它实际上可以编译。 这是C ++ 11,而C ++ 11C ++,直到采用新版本为止。
Ben Voigt

10
@BenVoigt啊,C ++ 11。我的错。对于那个很抱歉。
jamesdlin

5
@jamesdlin:自2011年8月21日起,该c++标记表示C ++ 11。如果人们想讨论旧版本,欢迎他们说C ++ 98或C ++ 03。明年的某个时候,裸c++标签将再次更改为C ++ 14。
Ben Voigt

2
@BenVoigt是的,我知道。我刚刚完全忘记了这是C ++ 11中添加的功能之一。
jamesdlin

6
值得注意的是,这立即使类型std::is_pod<T>::value变为非POD(通过验证),因此,从某种意义上讲,这等同于编写一个在初始化列表中设置相同值的非默认构造函数。
underscore_d

8

您可以通过使用构造函数来做到这一点,如下所示:

struct Date
{
int day;
int month;
int year;

Date()
{
    day=0;
    month=0;
    year=0;
}
};

或像这样:

struct Date
{
int day;
int month;
int year;

Date():day(0),
       month(0),
       year(0){}
};

在您的情况下,bar.c是未定义的,其值取决于编译器(而a和b设置为true)。


13
没有理由偏爱第一种形式。您应该使用初始化列表。
jamesdlin

@jamesdlin在99.9%的情况下表示同意,由于无数的原因,第二种方法非常可取。但是-只是扮演恶魔的拥护者!-如果不是ints成员是必须满足琐碎定义的自定义类(例如,没有非默认构造函数),那将是在主体中分配而不是在init列表中进行构造的原因。但是,在这种情况下有用的场景数量可能很少,因此init列表绝对应该是默认建议-很少有例外,它们经过仔细限定和证明是合理的,与此处不同。
underscore_d

1
@underscore_d不,这不是一个原因。您可以在所有情况下都使用初始化程序列表,除非成员变量是相互依赖的,并且这违反了3NF ;-)
user207421

@EJP这很可能是一个原因;我已经需要几次了。我认为您正在关注父级初始化,但是我正在谈论其成员。对于那些defaultctor不合适且标准布局排除非default构造函数的成员对象,必须以另一种方式执行“初始化”,operator=无论是初始化函数还是其他函数。在父代的构造函数中进行此“初始化”是有意义的,即在其主体中进行赋值。operator=这相当于帖子中的原语的体内分配。过度思考或切线,也许是正确的;-)
underscore_d

1
@GabrielStaples如果要初始化数组的单个元素,则可以,您需要在构造函数主体中执行此操作。显然,在构造函数主体中必须完成一些事情。我之前的评论专门讨论此答案中的特定示例。
jamesdlin

2

显式的默认初始化可以帮助:

struct foo {
    bool a {};
    bool b {};
    bool c {};
 } bar;

行为与returnbool a {}相同。bool b = bool();false

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.