首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >成员复制、位复制、浅拷贝和深拷贝有什么区别?

成员复制、位复制、浅拷贝和深拷贝有什么区别?
EN

Stack Overflow用户
提问于 2017-03-12 15:44:26
回答 2查看 11.2K关注 0票数 16

我在谷歌上搜索了这些术语,但我仍然很困惑。

有人说,成员复制是深拷贝,按位复制是浅表复制,但有人说不是。

有人能向我解释默认的复制构造函数和用户定义的复制构造函数使用哪种类型的副本吗?

EN

回答 2

Stack Overflow用户

发布于 2017-03-12 16:39:00

简短的版本:

  • 按位复制是内存块的副本。
  • 成员级副本是要求对正在复制的数据的结构有深入了解的副本。

说明这种差异的最简单方法是使用指针成员:

  • 通过执行按位复制,您将只复制它所指向的内存地址。
  • 通过执行一个按成员划分的副本,您将创建指针指向的内存的副本,然后使用指向该新内存区域的地址初始化复制的成员指针。

示例:

代码语言:javascript
复制
struct A 
{
   int* m_a;

   A() 
   {
      m_a = new int[1];
   }

   ~A()
   {
     delete [] m_a;
   }
};

A obj;

printf("%p\n", obj.m_a);  // prints: 0x10001000 (for example)

按位复制

代码语言:javascript
复制
A copiedObj = obj;        // the default copy constructor is employed
                          // it will perform a bitwise copy

printf("%p\n", copiedObj.m_a);  // prints: 0x10001000 - the same address

现在,obj.m_a和copiedObj.m_a都指向内存中的相同地址。

注意,使用这样的类定义,如果尝试删除这两个对象,就会遇到内存访问异常(要删除的对象将作为第二个对象尝试释放已被释放的内存)。

按会员顺序复制

代码语言:javascript
复制
struct A 
{
    A(const A& rhs)  // let's define a custom copy constructor
    {
        m_a = new int[1];
        memcpy(m_a, rhs.m_a, sizeof(int) * 1);
    }
}

A copiedObj = a;

printf("%p\n", copiedObj.m_a);  // prints: 0x9a001234 - a totally different address

我们在自定义复制构造函数中执行的自定义操作生成了原始对象的指针指向的内存的副本。

最后但并非最不重要的是,成员级的复制并不局限于复制构造函数。将其视为对对象所在的内存区域进行操作的操作。

票数 2
EN

Stack Overflow用户

发布于 2021-02-16 08:39:34

这四个术语:

  • 成员副本
  • 按位复制
  • 浅拷贝
  • 深拷贝

不存在于相同的意义轴上。

在大多数情况下,当大多数人在编程中说:“计算机,给我一份副本”时,大多数人都会期望从语义对象那里得到深拷贝

具体来说,在C++上下文中,这意味着现有对象的副本也递归地复制了所有子对象,不管它们是如何实现的。(指针、ints、其他复杂对象、.)

如果不考虑对象的某些直接内存成员实际上是指针(某种类型的),并且您只复制它们的“指针值”,而不是遵循间接和创建指向对象的适当副本,那么浅层复制就是所得到的结果。

当编译器执行简单的成员级复制(参见下面),并且对象包含(原始)指针时,浅层复制就是C++中的内容。如果您对任何对象进行简单的复制,那么浅层复制也是在C#或中得到的,因为在那里,“所有东西”都是一个指针/引用。

如果您有一个微不足道的可复制对象,例如只包含struct s的int,那么浅拷贝与深拷贝是相同的。

按位复制是在执行内存中对象的memcpy()时在C++中得到的。结果可能是语义上的深拷贝,或者(更可能是)浅拷贝(如果涉及指针的话),或者它可能只导致内存中的一串不再是复制的类型的有效对象的形式的位。

最后,是C++中的一个特定术语,由C++ Std调用,用于编译器生成的复制C‘for在被调用时所做的操作。具体地说:

非联合类X的隐式定义复制/移动构造函数执行其基和成员的成员级复制/移动。(...)

[class.copy.ctor]中,它接着描述了这意味着什么:

每个基或非静态数据成员都以适合其类型的方式复制/移动:(.)

(!)根据对象的不同,按语义上的副本可以等效为以上三种类型的所有

(我在这一点上注意到,C++ Std总是使用“成员级”,而不是“成员级”,但我的自动更正更倾向于“成员级”或“成员级”--这在谷歌搜索时可能会有所帮助。)

就我而言,,如果您有一个用户定义的复制ctor,则从不使用(应该)查看1:1的成员复制,因为如果您执行1:1的成员复制,您就不需要实现ctor,编译器将为您生成它。

来做一些比较:

  • 如果您有一个structof ints,那么一个按成员顺序复制的结果与按位复制的结果是相同的,它既是一个浅拷贝,也是一个深拷贝(嗯,没有深度可言)。
  • 如果您有一个struct of int*指针,则一个成员级副本与一个按位复制相同,它也是一个浅拷贝,但它不再是一个深拷贝,因为该副本将指向与原始副本相同的整数。
  • 如果您有一个包含任何非平凡对象(例如std::string)的结构,那么按位复制就不再有效,而成员级副本是浅的还是深的取决于子对象的实现:如果子对象在复制构造中实现了深度复制,则复制是深的。如果您有任何只做浅拷贝的子对象成员,那么成员级的复制也将是(部分)浅的。
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/42749439

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档