c++ - 我可以在 C++ 中使用 memcpy 来复制没有指针或虚函数的类吗

标签 c++ performance shallow-copy

假设我有一个类,如下所示;

class MyClass
{
public:
  MyClass();
  int a,b,c;
  double x,y,z;
};

#define  PageSize 1000000

MyClass Array1[PageSize],Array2[PageSize];

如果我的类没有指针或虚方法,那么使用以下内容是否安全?

memcpy(Array1,Array2,PageSize*sizeof(MyClass));

我问的原因是,我正在处理非常大的分页数据集合,如 here 所述,其中性能至关重要,而 memcpy 与迭代分配相比具有显着的性能优势。我怀疑应该没问题,因为“this”指针是一个隐式参数,而不是任何存储的参数,但是我应该注意其他隐藏的问题吗?

编辑:

根据尖牙的评论,数据不包括任何句柄或类似的引用信息。

根据 Paul R 的评论,我已经对代码进行了概要分析,在这种情况下,避免使用复制构造函数大约快 4.5 倍。这里的部分原因是我的模板化数组类比给定的简单示例要复杂一些,并且在为不允许浅复制的类型分配内存时调用放置"new"。这实际上意味着调用默认构造函数以及复制构造函数。

第二次修改

也许值得指出的是,我完全接受以这种方式使用 memcpy 是不好的做法,在一般情况下应避免使用。使用它的具体情况是作为高性能模板化数组类的一部分,其中包括一个参数“AllowShallowCopying”,它将调用 memcpy 而不是复制构造函数。这对诸如删除数组开头附近的元素以及将数据分页进出辅助存储等操作具有很大的性能影响。更好的理论解决方案是将类转换为简单的结构,但鉴于这涉及到大量代码库的重构,避免它不是我热衷于做的事情。

最佳答案

根据标准,如果程序员没有为类提供复制构造函数,编译器将合成一个显示默认成员初始化的构造函数。 (12.8.8) 但是,在 12.8.1 中,标准还说,

A class object can be copied in two ways, by initialization (12.1, 8.5), including for function argument passing (5.2.2) and for function value return (6.6.3), and by assignment (5.17). Conceptually, these two operations are implemented by a copy constructor (12.1) and copy assignment operator (13.5.3).

这里的关键词是“概念上”,根据 Lippman为编译器设计者提供了一个“出路”,以便在“平凡”(12.8.6)隐式定义的复制构造函数中实际执行成员初始化。

实际上,编译器必须为这些表现出行为的类合成复制构造函数,就好像它们正在执行成员初始化一样。但是,如果该类显示“按位复制语义”(Lippman,第 43 页),则编译器不必合成复制构造函数(这将导致函数调用,可能是内联的)并改为按位复制。此声明显然在 ARM 中得到支持。 ,但我还没有查到这个。

使用编译器来验证某些东西是否符合标准总是一个坏主意,但是编译代码并查看生成的程序集似乎可以验证编译器没有在合成的复制构造函数中进行成员初始化,而是在执行 memcpy 改为:

#include <cstdlib>

class MyClass
{
public:
    MyClass(){};
  int a,b,c;
  double x,y,z;
};

int main()
{
    MyClass c;
    MyClass d = c;

    return 0;
}

MyClass d = c;生成的程序集是:

000000013F441048  lea         rdi,[d] 
000000013F44104D  lea         rsi,[c] 
000000013F441052  mov         ecx,28h 
000000013F441057  rep movs    byte ptr [rdi],byte ptr [rsi] 

...其中 28hsizeof(MyClass)

这是在 MSVC9 下在 Debug模式下编译的。

编辑:

这篇文章的长短是:

1) 只要执行按位复制会表现出与按成员复制相同的副作用,标准就允许简单的隐式复制构造函数执行 memcpy 而不是按成员复制。

2) 一些编译器实际上执行 memcpys,而不是合成一个执行成员复制的简单复制构造函数。

关于c++ - 我可以在 C++ 中使用 memcpy 来复制没有指针或虚函数的类吗,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3021333/

相关文章:

android - 从android上的sqlite获取数据真的很慢

linq - 创建返回时LINQ是否会增加内存

scheme - 通过计划中的值(value)混淆

c++ - 是否可以使用 gtest 或 gmock 模拟被调用函数的返回值?

java - 你能在 C++ 中使用 Java Swing 吗?

C++ CURL Json 请求不一致 API 以进行消息发布

c++ - 关于多重继承和定义虚函数

c# - C#中的字符串操作优化

javascript - Object.assign() 创建的是深拷贝还是浅拷贝?

ios - 执行优先级非常低的代码