【问题标题】:when a structure has c-tor, why can't I statically initialize it?当结构具有 c-tor 时,为什么我不能静态初始化它?
【发布时间】:2012-08-28 15:45:31
【问题描述】:

我的问题:当一个结构有 c-tor 时,为什么我不能静态初始化它?

我的编译器声称:

type `myStruct' must be initialized by constructor, not by `{...}'

这是为什么呢?我正在使用 gcc 3.4.4 版(cygming 特殊,gdc 0.12,使用 dmd 0.125)

为了说明,这里是被编译器拒绝的struct

struct myStruct
{
    int a;
    double b;

    myStruct() { a= 0; b = 0.0; }
}

void main()
{
    myStruct ms = {7, 7.7}; // Now this compiler does not accept.
} 

【问题讨论】:

  • 示例代码需要花费数小时才能格式化,直到它被接受!它声称我没有正确缩进 4 个空格的代码。我愿意。我可以数到 4。 struct myStruct { int a;双乙; // 现在我在这里添加一个默认的 c-tor myStruct() { a= 0; b = 0.0; } } void main() { myStruct ms = {7, 7.7}; // 现在这个编译器不接受。 }
  • @Peter 无需手动操作。将代码粘贴到编辑器中,选择它,点击按钮(用于 Ctrl-K)。
  • 我想你在谈论数组初始化语法?因为你只能通过这种方式初始化 POD 类型...
  • 你认为你需要查看什么代码,@Robert?没有任何代码,这个问题对我来说似乎很清楚。
  • @RobKennedy Peter 问他为什么会遇到特定错误,但我假设他也想要一个能够产生他想要的效果的解决方案。对于前者,代码无济于事。对于后者,代码是必要的。

标签: c++ static constructor initialization structure


【解决方案1】:

包含用户定义的 c-tor 意味着它不再是聚合类型。如果struct 本身没有用户定义的 c-tor,但您有一个不是 POD 或聚合类型的 struct 的非静态数据成员,也会出现这种情况。

【讨论】:

  • 许多超快速答案的thnax。代码被序列化了——尽管我的问题被抓住了:) :) 再次感谢帮助!
  • @Jason 您的意思是聚合,而不是 POD。并非所有聚合都是 POD(在 C++11 中反之亦然)。
  • 超快,但无关紧要。谁说过关于 POD 的事。他在问聚合初始化,它不需要 POD,但(惊喜,惊喜)和聚合。
  • @JamesKanze 好的,已解决……你今天和我玩得很开心! :-)
  • C++11 如何改变这一点?我知道它对初始化程序有帮助以帮助处理非 POD,但它会影响聚合,只是 POD,...?
【解决方案2】:

因为语言是这样指定的...

原因是构造函数是将对象初始化为有效状态的指定方式,所以直接将值转储到字段中是没有意义的。想法是你要么有一个值的集合,要么有一个自包含的对象但你想做的事情会让两者兼而有之。

【讨论】:

    【解决方案3】:

    只有聚合可以使用初始化列表进行初始化。根据 8.5.1:1,包含用户提供的构造函数可防止结构或类成为聚合:

    8.5.1 聚合 [dcl.init.aggr]

    1 - 聚合是一个数组或一个类(第 9 条),没有用户提供的构造函数 [...]

    在 C++03 中,

    8.5.1 - 聚合 [dcl.init.aggr]

    1 - 聚合是没有用户声明的构造函数的数组或类(子句类)[...]

    聚合不同于 POD ( 9:10);并非所有聚合都是 POD,也不是所有 POD 都是聚合;具有用户提供的析构函数的类可以是聚合但不是 POD,而具有非复制非默认构造函数的类可以是 POD 但不是聚合。

    演示:

    #include <type_traits>
    #include <iostream>
    
    struct non_pod_aggregate { int i, j; ~non_pod_aggregate() {} };
    struct non_aggregate_pod { int i, j; non_aggregate_pod(int) {}
        non_aggregate_pod() = default; };
    
    int main() {
        std::cout << std::is_pod<non_pod_aggregate>::value << '\n'; // false
        std::cout << std::is_pod<non_aggregate_pod>::value << '\n'; // true
        non_pod_aggregate{0, 0};
        // non_aggregate_pod{0, 0}; // does not compile
    }
    

    在 C++03 中,所有 POD ( 9:4) 都是聚合,但仍有可能存在非 POD 的聚合;如上所述,用户提供的析构函数足以使结构失去 POD 的资格。

    【讨论】:

    • 请记住,他使用的是一个相当旧的 gcc 版本,所以它将是 C++03 而不是 C++11 ... C++11 放宽了一些关于什么的规则被认为是 POD 类型,而对于构造函数则不是。
    • C++03 标准的第 9/4 节规定:“POD 结构是一个聚合类,它没有非 POD 结构类型的非静态数据成员,非-POD-union(或此类类型的数组)或引用,并且没有用户定义的复制赋值运算符和用户定义的析构函数。" ...因此,为了成为聚合类型,POD- struct 不能有任何类型的用户声明的构造函数,并且包括非复制非默认构造函数。
    • @Jason 这是聚合初始化,因此 POD 规则并不完全相关。
    【解决方案4】:

    在 C++03 中,列表初始化仅适用于聚合。您需要更改代码以调用构造函数:

    myStruct ms;
    

    如果您希望能够为所有成员指定值,则需要添加一个带有足够参数的构造函数:

    struct myStruct
    {
        int a;
        double b;
    
        myStruct() : a(), b() { }
        myStruct(int a, double b) : a(a), b(b) { }
    };
    
    void main()
    {
        myStruct ms(7, 7.7);
    } 
    

    【讨论】:

      猜你喜欢
      • 2011-01-19
      • 2023-04-05
      • 1970-01-01
      • 1970-01-01
      • 2016-05-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多