【问题标题】:Force Default Initialized Constructor in POD?在 POD 中强制默认初始化构造函数?
【发布时间】:2015-07-19 09:32:10
【问题描述】:

有没有办法强制将默认的初始化构造函数用于 POD 类型。让所有的值如整数一样初始化为零?

struct MyPod
{
    int a; // whether a is initialized to zero is dependent on creation method
};

struct MyOtherNonPod
{
    int b;
    MyOtherNonPod() : b(0) // b initialized to zero regardless of creation method
    {}
};

MyPod* pod = new MyPod; // pod->a not initialized
MyOhterNonPod* otherPod = new MyOtherNonPod; // otherPod->b is initialized to zero

有没有一种方法可以做到这一点,而不必定义构造函数并手动初始化所​​有变量?但只是强制始终调用默认的初始化构造函数?

MyPod* pod = new MyPod{}; // pod->a is default initialized to zero

无论{} 是否存在,有没有办法强制使用上述构造函数?我的 POD 类中有很多变量名称很冗长,我宁愿消除类不会被初始化为零的不确定性,具体取决于我是否默认初始化。无需手动全部设置。

【问题讨论】:

  • MyOtherPod 具有用户指定的构造函数,因此不是 POD 对象。 open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4296.pdf
  • 一个选项是 struct MyPodV: MyPod { MyPodV(): MyPod() {} };MyPodV 不是 POD,但基类是,因此可能适合您的要求。
  • @MattMcNabb 是的,这可能是我见过的最好的解决方案,谢谢!如果您将其发布为答案,我会将其标记为解决方案。

标签: c++


【解决方案1】:

POD的定义是不能有用户定义的构造函数,所有成员都必须是POD。

所以,不,你不能。但看起来你不需要 POD。

#include <iostream>

struct NonPOD {
    int    i = {};
    double d = {};
    // NonPOD() = default;
};

int main() {
    NonPOD x;
    std::cout << x.i << ", " << x.d << "\n";
}

【讨论】:

  • 根据cppr,这不是一个聚合。 Nvm,它在 C++ 14 中,只是不在 C++11 中。
  • 有没有办法在不添加 = {} 的情况下做到这一点?
  • 标准没有说“用户定义”它说“非平凡”。 struct NonTrivial { NonTrivial(); }; struct Trivial { Trivial() {} };
  • @kfsone 嗯。是的,我在写这个答案的时候有两个想法。无论如何,对于真正的 POD,我们无法拥有 OP 想要的东西。
  • @Sehe 实际上,我收回了 - 标准说 A destructor is trivial if it is not user-provided and if 所以 - 它根本不能由用户提供。
【解决方案2】:

无法按照您的要求进行操作,因为 POD 可能没有用户声明的构造函数。一种替代方法是创建一个以 POD 作为基类的类:

struct MyPodV : MyPod
{
    MyPodV: MyPod() {}
};

然后您可以创建 MyPodV 对象,并且仍然将它们与期望 MyPod 的函数一起使用。

当然,您可能会忘记并创建MyPod 而不是MyPodV 的问题,因此与要求人们使用MyPod x{} 相比,这并没有太大的意义。不过,也许您可​​以使用命名约定来避免意外地自行创建 POD。

【讨论】:

    【解决方案3】:

    恐怕 C++ 中没有默认的自动初始化,至少不是你所期望的那样。

    据我所知,至少从 c++11 标准开始,您有三个选项可供选择:

    1. 为每个结构添加一个默认构造函数,这可能有点乏味。

      //Init by default constructor
      struct POD3{
          int a;
          int b;
          char c;
          POD3(): a{}, b{}, c{} {};
      };
      POD3 stackPod3;
      POD3* heapPod3 = new POD3;        
      
    2. 为结构的每个成员添加默认初始化,这就是我要做的。

      //Init by field
      struct POD{
          int a{};
          int b{};
          char c{};        
      };
      POD stackPod;
      POD* heapPod = new POD;
      
    3. 或者在创建对象时冒险并依赖正确的语法,这是最糟糕的选择。

      //Init by object creation
      struct POD2{
          int a;
          int b;
          char c;        
      };
      POD2 stackPod2{};
      POD2* heapPod2 = new POD2{};
      

    正如上面已经提到的,我个人的看法是,第二个选项最有利于代码的可读性,并且丢失成员的机会非常低。

    【讨论】:

    【解决方案4】:

    是的,有一种方法可以在 C++11 中实现。代码如下:

    #include <iostream>
    
    struct MyPod
    {
        int a; // whether a is initialized to zero is dependent on creation method
    };
    
    
    int main()
    {
        MyPod* pod = new MyPod{ 23 }; // pod->a initalized to 23
    
    }
    

    在这种情况下有必要使用花括号,因为这样做是按顺序初始化每个成员。如果MyPod 中有更多类型,那么它可能如下所示:

    #include <iostream>
    
    struct MyPod
    {
        int a; 
        bool b;
        double c;
    };
    
    
    int main()
    {
        MyPod* pod = new MyPod{ 23, false, 32.93 }; 
    }
    

    【讨论】:

    • 我希望它被默认初始化(为零),而不必依赖于它是如何初始化的。我希望它被零初始化,而不必依赖于使用哪种方法来初始化它,而不必手动将每个变量设置为零。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-06-17
    • 2019-10-07
    • 1970-01-01
    • 2021-12-16
    • 2015-07-10
    相关资源
    最近更新 更多