【问题标题】:How to copy a structure with pointers to data inside (so to copy pointers and data they point to)?如何复制带有指向内部数据的指针的结构(以便复制它们指向的指针和数据)?
【发布时间】:2011-01-31 06:05:55
【问题描述】:

所以我有一个类似的结构

struct GetResultStructure
{
  int length;
  char* ptr;
};

我需要一种方法来制作它的完整副本,这意味着我需要一个副本来拥有一个结构,其中新的 ptr 指向我在原始结构中拥有的数据的副本。这怎么可能?我的意思是我拥有的任何包含 ptrs 的结构都将具有一些具有其长度的字段或者任何方式如何创建这样的功能?

【问题讨论】:

  • 为什么不写一个简单的拷贝构造函数?
  • @Naveen:真正的问题是,这个裸指针在这里做什么:)

标签: c++ memory data-structures boost


【解决方案1】:

对于您描述的特定场景,请使用std::vector 或其他一些序列容器。如果这样做,那么只需复制 GetResultStructure 类型的对象也会复制指向的数据:

struct GetResultStructure {
    std::vector<char> data;
};

GetResultStructure a = GetData();
GetResultStructure b = a; // a and b have distinct, equivalent data vectors

通常,当您确实需要自己实现时,您可以通过实现复制构造函数和复制赋值运算符来实现。最简单的方法是使用复制和交换习语,What is the copy-and-swap idiom? 中有详细介绍

【讨论】:

    【解决方案2】:

    实现它几乎取决于您。通常你想把它作为一个复制构造函数来做,所以你只需要在一个地方做。不幸的是,没有真正的魔法可以避免告诉计算机如何复制你的结构。

    当然,这仅适用于您的结构确实与已经编写的内容有很大不同的情况。您给出的那个看起来像一个字符串或(可能)向量的 lot。除非你真的需要实现一些新的东西,否则你最好只使用已经提供的一个。

    【讨论】:

      【解决方案3】:

      复制构造函数和赋值运算符都应该实现(以上述方式)。然而,在此过程中可能有帮助的一种技术是在复制指针数据时使用取消引用运算符 (*)。这将复制指针数据而不是内存位置。如果你这样做 ptr1 = ptr2 它只是将 ptr1 的内存位置设置为 ptr2 这就是我们取消引用的原因。

      例如,我将展示一个复制构造函数的简单示例:

      GetResultStructure(const GetResultStructure& other)
          : length(other.length), ptr(new char[length]) // <--- VERY _important_ - initialization of pointer
      {
          // Alternatively, put your initialization here like so:
          // ptr = new char[length];
          for(int i=0;i<length;++i)
          {
              ptr[i]  = new char;
              *ptr[i] = *other.ptr[i]; // Copy the values - not the memory locations
          }
      }
      

      然后显然一定要清理你的析构函数以防止内存泄漏。

      问候,
      丹尼斯 M.

      【讨论】:

      • ptr 可能指向一个 array 而不是单个项目(您甚至在初始化 ptr 时承认这一点),但上面的代码只会复制第一项那个数组。
      • ptr[i] = new char; 不正确。也就是说,有一种算法可以执行此操作,std::copy(other.ptr, other.ptr + other.length, ptr); 更简洁。虽然通常最好在初始化列表中初始化成员,但如果要将结果分配给原始指针,则建议不要执行动态分配,以避免发生异常时潜在的内存泄漏。
      【解决方案4】:
      GetResultStructure doCopy(GetResultStructure const& copy) {
        GetResultStructure newstruct;
        newstruct.length = copy.length;
        newstruct.ptr = new char[newstruct.length];
        memcpy(newstruct.ptr, copy.ptr, newstruct.length*sizeof(char));
        return newstruct;
      }
      

      应该很简单。是的,sizeof(char) 并不是真正需要的,但它可以显示如何处理其他数据类型。

      【讨论】:

      • 为什么要用函数而不是复制 ctor?
      • 虽然memcpy 适用于char 的数组,但它不适用于任何非POD 类型的数组。 std::copy 几乎总是更可取,因为它实际上复制了对象,而不仅仅是内存中的原始字节。
      【解决方案5】:

      既然你把它标记为 C++:写一个copy constructor 和一个assignment operator, 您在其中实现深层复制代码:

      struct GetResultStructure
      {
          GetResultStructure(const GetResultStructure& other)
          {
              // Deep copy code in here   
          }
          GetResultStructure& operator=(const GetResultStructure& other)
          {
              if (this != &other) {
                  // Deep copy code in here
              }
              return *this
          }
          int length;
          char* ptr;
      };
      

      【讨论】:

      • 我其实最喜欢你的回答。但是我有一个问题要问你——在这样的例子中如何实现“深拷贝代码”?
      • 在你的情况下,我假设它看起来像这样:length = other.length; ptr = new char[length]; memcpy(ptr, other.ptr, length);。而且您必须删除“operator =”中的旧ptr数据。抱歉,现在没有太多时间进一步解释:\
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-07-16
      • 1970-01-01
      • 2018-05-16
      • 2015-02-16
      • 2017-06-03
      相关资源
      最近更新 更多