【问题标题】:C++ Deep Copy of a structure that embeds many simple variables plus one nested structure ..(memcpy?)嵌入许多简单变量和一个嵌套结构的结构的 C++ 深度副本..(memcpy?)
【发布时间】:2011-04-16 14:22:45
【问题描述】:

我有

struct  Parent
{
    int child1;
    int child2;
     char child3;
     float child 4;
     anotherStruct child5;
};

typedef struct
{
    unsigned char  x;
    int            y;
    char           z;
    float          a;
    int            b;
    char           c;
    etc ..
  } anotherStruct;

Parent   myFirstParent;
Parent   mySecondParent;

///I want to do a deep copy of myFirstParent into mySecondParent. 
//does the follwowing work for that purpose??
memcpy (&mySecondParent, &myFirstParent, sizeof(myFirstParent);

我自己正在调查答案,但同时由于时间限制,我发布了这个问题。提前致谢。

【问题讨论】:

  • "...因为时间紧迫" 这有什么关系?

标签: c++ nested structure memcpy deep-copy


【解决方案1】:

在您的情况下,分配应该可以正常工作:

mySecondParent = myFirstParent;

毕竟,没有一个结构定义指针。

另外,如果有指针,即使memcpy 也不起作用,因为它不进行深度复制。在这种情况下,您必须手动复制指针的内容

顺便说一句,您的代码无法编译,因为您在定义它之前使用了anotherStruct。请在Parent之前定义anotherStruct

【讨论】:

  • 如果 Parent 结构有 std::map 或 std::string 作为其成员之一,mySecondParent = myFirstParent 是否仍然有效?
  • @Shyam:是的。所有标准容器/类型都支持值语义,这意味着“赋值”确实“深度复制”了对象。
【解决方案2】:

根据经验

记住一件事:memcpy() 是邪恶的!这是一个你永远不应该在 C++ 中使用的 C 构造。 memcpy() 作用于位和字节,而不是对象。在最坏的情况下,它没有考虑到您正在复制的对象中实际存储的内容,从而导致错误的结果,甚至是考虑特殊情况的丑陋代码。永远不要在 C++ 代码中使用 memcpy()。总是有更好、更面向对象的方法来做同样的事情。

这可能不适用于您的情况,因为您没有使用免费商店,但适用于您可以使用免费商店的时候。

SOURCE

【讨论】:

    【解决方案3】:

    由于您的类中没有指针,因此默认编译器生成的复制构造函数和assignemnt 运算符版本将正常工作(执行您所谓的深层复制)。

    从技术上讲,它是一个浅拷贝。深拷贝是指您的类包含指针并且您需要复制指针内容。

    没有 memcpy 应该可以正常工作(永远不应该用来复制 C++ 对象)

    Parent   p1;
    Parent   p2(p1);   // Make a copy of p1 into p2.
    Parent   p3;
    
    p1 = p3; // Use assignment operator works fine.
    

    【讨论】:

      【解决方案4】:

      一个简单的分配结构将适合您。一般来说,cimpiler(如 Microsoft 编译器和 GCC)会选择最有效的内存复制方法。对于小的或简单的事情,一系列寄存器加载和保存通常是性能最好的。编译器可能会为某些事情选择 memcpy()。

      其他答案表明 memcpy() 永远不应与 C++ 类一起使用。这通常是正确的,但是如果您知道自己在做什么,则可以在某些情况下使用它。但这几乎是不必要的。

      在 AMD 和 Intel x86/x64 处理器上,memcpy() 始终生成(或使用)“rep moved”指令。多年来,所有现代处理器都针对此指令进行了优化,具有特殊的微代码或其他内部选项,以确保良好地执行中小型内存移动。

      最好的办法就是在调试器中查看生成的汇编语言代码。如果您的结构分配没有以一系列简单的加载/存储或 memcopy (rep moved) 结束,那么您可以自己使用 memcpy() 编写代码。这可以正常工作,因为您的类和结构使用“普通旧数据”。正如另一个答案所说,如果您的结构包含指针,那么您将需要代码来处理那些作为浅拷贝或深拷贝,或引用计数的对象。

      与往常一样,对于“热”代码路径,分析器和性能测量是必不可少的工具。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2015-05-13
        • 1970-01-01
        • 2019-03-15
        • 1970-01-01
        • 2019-06-24
        • 2014-10-12
        • 2014-06-19
        • 1970-01-01
        相关资源
        最近更新 更多