C++:使用memset还是结构体构造函数?哪个更快?

8

我在C++中遇到了一个问题,不知道哪种方法更好:

我使用结构体来管理消息队列中的客户端,结构体如下所示:

typedef struct _MsgClient {
  int handle;
  int message_class;
  void *callback;
  void *private_data;
  int priority;
} MsgClient;

所有这些都是POD实体。

现在,我有一个结构体数组,我在其中存储我的客户端(由于内存限制,我使用数组来限制碎片化)。因此,在我的类中,我有像这样的东西:

class Foo
{
private:
  MsgClient _clients[32]; 

public:
  Foo()
  {
     memset(_clients, 0x0, sizeof(_clients));
  }

}

现在我在 Stack Overflow 上读到,使用 memset 在 C++ 中是不好的,我最好为我的结构体使用构造函数。我想到了以下代码:

typedef struct _MsgClient {
  int handle;
  int message_class;
  void *callback;
  void *private_data;
  int priority;
  // struct constructor
  _MsgClient(): handle(0), message_class(0), callback(NULL), private_data(NULL), priority(0) {};
} MsgClient;

如果使用结构体的构造函数来初始化foo,就可以不需要使用memset了。但我的担忧是,当foo被初始化时,结构体构造函数将被调用32次,而不是优化为简单地清零由数组占用的内存。

您对此有何看法?
我刚刚发现了这篇文章:Can a member struct be zero-init from the constructor initializer list without calling memset? ,它适用于我的情况吗(我的情况不同:我有一个数组,而不是结构体的单个实例)?
此外,根据这篇文章的说法,向我的结构体添加构造函数将自动将其转换为非POD结构体,这是正确的吗?


4
我无法回答整个问题,但是是的,向结构体或类添加自定义构造函数将使其成为非POD结构。 - user457812
+1 这是一个有趣的问题 - 即使您拥有一亿个客户的数组,我也怀疑使用构造函数会导致性能问题。适当地初始化每种类型而不仅仅是将内存清零是最安全的做法。但我也很想知道 c++ 实现在初始化方面背后做了什么 - 是否实际上调用了 memset。 - Tom
只要你知道,如果你在这个类中放置了一个虚函数,memset会有效地破坏它。 - Nicol Bolas
@Nicol:是的,通过查看其他类似的问题,我也是这样理解的。对于我来说,我不会同时使用memset和构造函数,因为它们是互斥的。 - Gui13
2个回答

13
在符合标准的实现中,可以在构造函数初始化列表中使用空成员初始化程序来对数组进行 值初始化。对于你的数组成员,这将会产生每个数组元素的 零初始化 效果。
编译器应该能够非常高效地完成这项工作,因此您不需要为您的 struct 添加一个构造函数。
例如:
Foo() : _clients() {}

是的,这可能会通过memset()实现 - 无需考虑可移植性,编译器会想出最佳实现方法。 - sharptooth
1
虽然我想通过查看汇编输出来测试这一点,以便在编译器被强制假定初始化值将被使用的情况下进行。 - Omnifarious
好的,这个结构在编译方面似乎是有效的。我会进一步测试它,但我感觉这是正确的做法 :) - Gui13
@VJo:尝试查看《8.5 [dcl.init]》以获取有关_value-initialization_的描述,查看《12.6.2 [class.base.init]/3》以获取有关基类和成员初始化的描述。GCC已经符合规范很长时间了(永远?)。 - CB Bailey
有趣。我错了(这就是你写的对的;)。这甚至在gcc上也可以工作。我一定把它和POD对象创建混淆了,后者会被填充垃圾。 - BЈовић
显示剩余2条评论

3
你可以在 C++ 中自由地使用 memset,只要你知道自己在做什么。 关于性能 - 真正快的方法是在发布配置下构建程序,然后在反汇编器中查看生成的代码。
使用 memset 比逐个初始化对象听起来更快。然而,编译器有可能生成相同的代码。

2
只是一个小小的吹毛求疵:那个句子应该是:“看到为什么方式更快的唯一方法是...然后通过分析进行比较。” 查看反汇编代码不一定是确定哪个更快的最简单方法。 - Oliver Charlesworth

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接