【问题标题】:Initializing default values in a struct初始化结构中的默认值
【发布时间】:2013-05-28 00:14:33
【问题描述】:

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

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

我是否正确假设我最终会得到一个名为 barstruct 项目,其中包含元素 bar.a = truebar.b = true 和未定义的 bar.c

【问题讨论】:

  • 栏只是一个重命名,如果你使用c++你不需要这样做
  • @aaronman 不,bar 是一个变量。
  • @aaronman 我认为您将其与typedef struct foo {} bar; 混淆了。
  • 那么,如果bar 是结构,那么foo 是什么?这是否与定义foo 结构并单独将新变量bar 声明为foo 类型相同?
  • bar 只是一个 foo 对象。等同于struct foo {//something};foo bar;

标签: c++


【解决方案1】:

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

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

澄清一下:这些称为大括号或等号初始化器(因为您也可以使用大括号初始化而不是等号)。这不仅适用于聚合:您可以在普通类定义中使用它。这是在 C++11 中添加的。

【讨论】:

  • 反对者:请先熟悉标准的 C++11 更新,然后再向人们介绍什么是合法的或不合法的。 It actually compiles just fine.这是C++11,C++11 C++,直到采用新版本。
  • @jamesdlin:自 2011 年 8 月 21 日起,c++ 标签表示 C++11。如果人们想讨论旧版本,欢迎说 C++98 或 C++03。明年某个时候,裸露的c++ 标签将再次更改为 C++14。
  • 值得注意的是,这立即使类型成为非 POD(通过 std::is_pod<T>::value 验证),因此在这个意义上,相当于编写了一个在初始化程序中设置相同值的非默认构造函数列表。
  • 实际上大括号初始化只有在 C++11 中没有默认成员初始化器时才允许。 C++14 解除了这个限制。 ideone 使用 C++14,但如果您使用任何 C++11 编译器,该代码将失败。 en.cppreference.com/w/cpp/language/aggregate_initialization
  • 如果结构是使用 typedef 定义的,比如 C 风格呢?还在初始化吗?
【解决方案2】:

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

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

根据 C++ 标准第 8.5.12 节:

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

对于原始内置数据类型(bool、char、wchar_t、short、int、long、float、double、long double),只有 global 变量(所有静态存储变量)如果没有显式初始化,则默认值为零。

如果您真的不想以未定义的bar.c 开头,您还应该像为bar.abar.b 那样初始化它。

【讨论】:

  • @CaptainObvlious 刚刚更新,抱歉我被其他东西分心了,而不是电脑。
  • 它不是“未定义”,它是未初始化的,意味着它有一个不确定的值
  • 我认为 OP 的意思是说 value 是未定义的,而不是成员。
【解决方案3】:

您可以使用构造函数来完成,如下所示:

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)。

【讨论】:

  • 没有理由偏爱第一种形式。您应该使用初始化列表。
  • @jamesdlin 在 99.9% 的情况下同意,其中出于无数原因,第二个非常可取。然而——只是为了扮演魔鬼的拥护者! - 如果成员不是ints,而是必须满足琐碎定义的自定义类(例如,没有非默认构造函数),那将是在主体中分配而不是在初始化列表中构造的原因。但是,这在其中有用的场景数量可能很少,因此初始化列表绝对应该是默认推荐 - 与这里不同的是,极少数例外情况经过仔细限定和证明。
  • @underscore_d 不,这不是这样的原因。您可以在所有情况下使用初始化列表,但成员变量相互依赖的情况除外,这违反了 3NF ;-)
  • @EJP 这很可以是一个原因;我已经需要它好几次了。我认为您专注于父级初始化,但我说的是它的成员。对于default ctors 不合适且标准布局排除非default 构造函数的成员对象,一个必须 以另一种方式执行“初始化”,无论是operator= 还是一个init 函数或其他。在父类的构造函数中执行此“初始化”是有意义的,即在其主体中分配。 operator= 这里相当于帖子中的原语体内分配。可能是过度思考或切线,但确实如此;-)
  • @GabrielStaples 如果您正在初始化数组的各个元素,那么是的,您需要在构造函数主体中执行此操作。显然有些事情必须在构造函数体中完成。我之前的评论是专门讨论这个答案中的具体例子。
【解决方案4】:

显式默认初始化会有所帮助:

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

行为bool a {}bool b = bool(); 相同并返回false

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-12-29
    • 1970-01-01
    相关资源
    最近更新 更多