使用C风格的现代c++类

C style use of a modern C++ class

本文关键字:c++ 风格 使用      更新时间:2023-10-16

我有一个这样的类:

片段1:

struct B
{
    int member;
    // more complex members e.g. arrays of structs etc
};

这个类在代码中使用,假设它是一个C风格的结构体(例如在memcpymemset等中使用)

作为良好编程原则的一部分,我正在考虑这样修改B:

片段2

struct B 
{
    B() {}
    int member;
    // more complex members e.g. arrays of structs etc
};
这是我的理解。如果我说错了,请指正a.代码段1定义了B,它是一个POD,而代码段2定义了B,它不是一个POD, ANDb.在代码片段2中,b仍然可以合法地用于C风格的用途,如memset和memcpy
  1. std::is_pod: false
  2. std::is_trivial: false
  3. std::is_trivially_copyable: true
  4. std::is_trivial: false

扩展,我也将遵循大3(或者大5)的规则,我将添加复制赋值和复制构造函数。

片段3:

struct B
{
    B() {}
    ~B(){}
    B& operator=(B &){ return *this; }
    B(B const &r){}
    int member;
    // more complex members e.g. arrays of structs etc
};
这是我的理解。如果我说错了,请指正a.在代码片段3中,B现在不能再合法地用于C风格的用途,如memset和memcpy

  1. std::is_pod: false
  2. std::is_trivial: false
  3. std::is_trivially_copyable: false
  4. std::is_trivial: false

我需要了解在代码片段2和代码片段3中向B添加各种成员对B的C风格使用的影响。

类的C风格使用真的是基于is_trivially_copyable还是基于is_trivial(这是更严格的)?

阅读$3.9/2向我表明,在c++ 11 中"is_trivially_copyable"才是真正的决定标准。然而,一些旧的c++书籍(例如,c++简而言之)指出,标准是关于POD与非POD的,我知道c++ 11的规则自那以后发生了变化。

pete的反应似乎表明琐碎性是必要的标准

如果您的结构只包含POD数据成员,并且不负责管理任何资源,例如动态分配的内存,则绝对没有理由定义析构函数、复制构造函数和赋值操作符。我最多只能添加一个构造函数来初始化数据成员。在c++ 11中,这可以通过使用非静态数据成员初始化器轻松实现。

struct B
{
    int member = 0; // this will initialize the data member to 0
};

您还可以添加一个构造函数,该构造函数接受int,并允许您将member初始化为任何所需的值。在这种情况下

struct B
{
    int member;
    explicit B(int member = 0) : member(member) {}
};

这两个变化将使你的类平凡地可复制(9/6)和标准布局(9/7),这意味着你将能够使用它们与c风格的函数。


从评论中的讨论来看,似乎您不一定对能够初始化所有数据成员感兴趣,但仍然希望提供默认构造函数。

struct B 
{
    B() {}
    int member;
    // more complex members e.g. arrays of structs etc
};

这是一个坏主意,因为它没有为类添加任何有用的东西,并且使它变得非平凡,因为它现在有了一个非平凡的默认构造函数。如果你真的想定义一个默认构造函数,你应该显式地用default来代替它。

struct B 
{
    B() = default;
    int member;
    // more complex members e.g. arrays of structs etc
};

这使类变得简单,并且具有标准的布局,允许您将其与C风格的函数一起使用。