【问题标题】:c++11 struct initialization compilation errorc++11 struct初始化编译错误
【发布时间】:2019-07-10 09:47:30
【问题描述】:
struct SS {int a; int s;};

int main ()
{
   vector<SS> v;
   v.push_back(SS{1, 2});
}

代码可以编译没有任何错误。但是,当在类中初始化结构时,出现编译错误。谁能解释一下?

struct SS {int a = 0; int s = 2;};

错误:

In function ‘int main()’:
error: no matching function for call to ‘SS::SS(<brace-enclosed initializer list>)’
     v.push_back(SS{1, 2});
                        ^
note: candidates are:
note: constexpr SS::SS()
 struct SS {int a = 0; int s = 2;};
        ^
note:   candidate expects 0 arguments, 2 provided
note: constexpr SS::SS(const SS&)
note:   candidate expects 1 argument, 2 provided
note: constexpr SS::SS(SS&&)
note:   candidate expects 1 argument, 2 provided

【问题讨论】:

    标签: c++ c++11


    【解决方案1】:

    在 C++11 中,当您像在此处一样在声明点使用非静态数据成员初始化时:

    struct SS {int a = 0; int s = 2;};
    

    您将班级设为非聚合。这意味着您不能再像这样初始化实例:

    SS s{1,2};
    

    要使这种初始化语法适用于非聚合,您必须添加一个双参数构造函数:

    struct SS 
    {
      SS(int a, int s) : a(a), s(s) {}
      int a = 0; 
      int s = 2;
    };
    

    此限制已在 C++14 中解除。

    请注意,您可能希望为该类添加一个默认构造函数。用户提供的构造函数的存在会禁止编译器生成默认构造函数。

    见相关阅读here

    【讨论】:

    • 对,我正要回答类似的问题。通过添加自定义构造函数SS() {},也可以看到没有 C++11 特性。
    • C++14 将不再将具有类内初始化器的类排除在聚合之外;见open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3653.html
    • @bames53 谢谢,我不知道。这是个好消息。我发现这个特定的规则过于严格。
    【解决方案2】:

    使用默认成员初始化器将类/结构呈现为非聚合:

    § 8.5.1 聚合

    聚合是一个数组或一个类(第 9 条),没有用户提供的构造函数 (12.1),非静态数据成员没有大括号或等式初始化器 (9.2),没有私有或受保护的非静态数据成员(第 11 条),没有基类(第 10 条),也没有虚函数(10.3)。

    聚合和非聚合的语义不同:

    聚合(例如,数组和结构):

    Initialize members/elements beginning-to-end.
    

    非聚合:

    Invoke a constructor.
    
    v.push_back(SS{1, 2}); // Error, it tries to call SS constructor
    

    这意味着你现在需要一个构造函数:

    struct SS 
    {
      SS(int a, int s) : a(a), s(s) 
      {
      }
      int a = 0; 
      int s = 2;
    };
    

    【讨论】:

    • 有趣的是,这在 C++1y 中不再适用,允许聚合成员具有大括号或等式初始化器。 N3690 §8.5.1/7 谈到从支撑初始化列表初始化聚合:“如果列表中的 initializer-clauses 少于聚合中的成员,则每个成员都没有显式初始化应从其 brace-or-equal-initializer 进行初始化,或者,如果没有 brace-or-equal-initializer,则从空的初始化器列表 (8.5.4) 。”
    【解决方案3】:

    我遇到了同样的问题。在我的例子中,我有两个 structs,它们都有一些构造函数,包括复制构造函数,从抽象父级继承。

    当上面的建议没有帮助时,我终于意识到我需要从复制构造函数中删除 explicit 说明符并删除错误。

    我想我会分享一下,以防另一个可怜的人像我刚刚那样发现这个错误。

    【讨论】:

      猜你喜欢
      • 2021-09-21
      • 2023-03-19
      • 1970-01-01
      • 1970-01-01
      • 2016-02-08
      • 1970-01-01
      • 1970-01-01
      • 2016-01-04
      相关资源
      最近更新 更多