在c++中如何将一个数据结构中的数据复制到另一个数据结构中

How does a copy of the data in one data structure to another work in C++?

本文关键字:数据结构 数据 一个 复制 另一个 c++      更新时间:2023-10-16

我有一个类,看起来像:

class A
{
  public:
       A();
       void MethodThatWillNotBeInOtherStructure();
       inline int getData() { return data; }
       inline void setData(int data_) { data = data_; }
  private:
       int data;
}

和如下结构:

struct B
{
  public:         
       inline int getData() { return data; }
       inline void setData(int data_) { data = data_; }
  private:
       int data;
}

如何将A的实例复制到B而不单独设置字段?我知道我可以,因为我已经看到的代码,将一个void*说a,并将其传递给一个函数期望B,它的工作。我最大的问题是,这是如何工作的?我想它与内存有关,但我不知道结构和类的内存布局将如何。例如,在其中一个中而不在另一个中的函数如何不妨碍内存内存?有人能给我解释一下吗?

好的,让我解释一下。我并不是说我会在可重用代码中这样做,也不是说我会使用它。我还是想知道它是怎么工作的。类的内存布局与结构不同吗?方法是如何存储的?数据存储在哪里?

谢谢!

通过void *相互复制两个不相关的结构只有在两个结构具有相同的内存布局时才能正常工作。否则复制失败。

请注意,上面代码中结构AB的对象将具有相同的内存布局,因为它们的成员变量是相同的。

通过void *进行复制是有效的,因为它只是将一个结构对象占用的实际内存复制到另一个结构对象占用的内存中。

以这种方式复制两个不相关的结构基本上是一个坏主意。

考虑结构中有指针成员的情况,memcpy只会导致指针成员的浅拷贝,如果其中一个对象结束其生命周期,那么最终,另一个对象将留下一个悬空指针成员。这将最终导致未定义的行为(很可能导致崩溃)。

方法如何存储?数据存储在哪里?
普通函数(非虚函数)将存储在程序代码部分的某个地方。这个位置对于类/结构的所有实例都是相同的,因此它不是类/结构的每个对象的内存分配的一部分。

在虚成员函数的情况下,由于虚函数的存在,类/结构的大小确实受到影响,类/结构的每个对象在每个this中都有一个称为vptr的特殊指针。注意,这是编译器的实现细节,编译器可以选择以不同的方式实现它。

当您使用不安全的机制(如memcpy)来复制结构时,了解内存布局非常重要。一旦以后修改了它,你的整个逻辑可能会搞砸。

类的

对象不包含函数。对象的内存只包含它的属性和所需的大小。另一方面,函数是整个程序中常见的可执行代码段,不会影响结构体的内存布局。

我建议您定义operator=,构造函数来适当地将一个对象转换为另一个对象。

关于memcpy的另一个小问题是,如果类具有虚函数,则对象可能包含虚指针。额外的指针数据也可以复制到目标内存;这不是很好!

可以使用memcpy将A复制到B,因为它们具有相同的成员变量。函数不是实例的一部分,所以它们无关紧要。

我不建议使用这种方法。如果A或B发生变化,那么您的副本将在运行时失败。你可以为B创建一个a的构造函数,它接受a,一个转换函数,或者别的什么。虽然它需要更多的代码,但它允许对结构进行更改。

您最好的选择可能是实现结构B的构造函数,该构造函数接受对结构a的const引用,直接使用该构造函数或使用赋值操作符(对于非平凡情况可能需要实现赋值操作符)。

A a;
... (populate a)
B b(a); //If you want to set b to a at instantiation.
b = B(a); //If you want to overwrite an existing instance of struct B with a.
编辑:

为了响应您的编辑,它完全依赖于编译器。事实上,它对类的工作完全依赖于编译器的细节,因为据我所知,它不受标准的支持。编译器开发人员可以通过使它适用于CLASS而不适用于STRUCT(反之亦然)来惹恼人们。

也就是说,我从未在我使用过的任何编译器中看到任何差异。