如何通过复制构造函数复制内置数组?

How to copy a built-in array via copy-constructor?

提问人:Itachi Uchiwa 提问时间:8/16/2021 更新时间:8/16/2021 访问量:657

问:

我们知道,内置数组既不能复制也不能分配。因此,如果它是类/结构/联合的成员数据,则可以让编译器发挥其魔力来复制它们:

struct ArrInt5{
    ArrInt5() = default;
    ArrInt5(ArrInt5 const&) = default; // OK 
    int a[5];
};

ArrInt5 a, b = a; // OK
  • 有时情况并非如此,例如,如果数组包含非默认可构造对象的对象。在那 我们确实需要定义我们的 copy-ctor 来完成这项工作:

      struct Bar{
          // deleted default ctor
          Bar(int x) : x_(x){}
          int x_ = 0;
      };
    
      struct Foo{
          Foo();
          Foo(Foo const&);
    
          Bar arr_[5];
      };
    
      Foo::Foo() : arr_{0, 1, 2, 3, 4}
      {}
    
      Foo::Foo(Foo const& rhs) : arr_{rhs.arr_[0], rhs.arr_[1], rhs.arr_[2], rhs.arr_[3], rhs.arr_[4]}
      {}
    
  • 正如你所看到的,有一个内置的数组,里面有五个类型的对象,该类型不是默认构造的,所以默认的 ctor 和复制的 ctor 必须初始化它 ()。Foostruct Bararr_

  • 问题是:如果该数组的大小很大,比如说 100 万个元素,如何初始化该数组?我应该逐个元素硬拷贝它们吗?还是有一些解决方法?

    • 我知道很多人会建议我使用等效的 STL 容器,但我不在这个话题上,我是在问我的内置非默认可构造对象数组是否有解决方法。std::array
C++ 数组复制 构造函数

评论

3赞 HolyBlackCat 8/16/2021
不可能,AFAIK。
2赞 Human-Compiler 8/16/2021
据我所知,唯一的解决方案使用 ,或者滚动您自己的等价于 .具有数组数据成员的类类型可以使用默认复制构造函数自动合成复制,因此需要 1 级间接才能自动生成此效果(无论基础类型是否为默认可构造)std::arraystd::array
0赞 Phil1970 8/16/2021
Foo(Foo const&) = default;将正确复制数组,因为它是第一个示例。我不明白这个问题的目的。因此,您不需要定义它,只需要求编译器生成默认值即可。

答:

5赞 Human-Compiler 8/16/2021 #1

自动生成此效果的唯一方法是将数组包装在某种类类型中,该类类型具有编译器生成的复制构造函数(例如,ed 构造函数)。在您的特定示例中,您可能只是被编辑:defaultFoo(const Foo&)default

struct Foo{
    Foo();
    Foo(Foo const&) = default;
    // This generates your:
    // "Foo::Foo(Foo const& rhs) : arr_{rhs.arr_[0], rhs.arr_[1], rhs.arr_[2], rhs.arr_[3], rhs.arr_[4]}"
    // by the compiler

    Bar arr_[5];
};

但是,上述方法仅在您的复制逻辑微不足道时才有效。对于更复杂的复制,你不能总是有一个复制构造函数 - 但我们可以更普遍地解决这个问题。default

如果将任何类型/大小的数组数据成员包装在 or 中,并确保它具有编译器生成的复制构造函数,则在构造函数中复制很容易。structclass

例如:

template <typename T, std::size_t N>
struct Array {
  ...
  T data[N];
};

这允许复制的简单情况:

Array<Bar,1000000> a = {{...}};
Array<Bar,1000000> b = a; 

或者更复杂的在构造函数中复制的情况,它可能需要比编译器生成的逻辑更多的逻辑:

class Foo {
  ...
  Foo(const Foo& other);
  ...
  Array<Bar,100000> arr_;
};

Foo::Foo(const Foo& other)
  : arr_{other.arr_}
{
  ... other complex copy logic ...
}

在这一点上,恭喜你 -- 你已经发明了 std::array! 被添加到标准库中,正是因为在不必更改语言本身的情况下引入库解决方案来解决这个问题非常简单。不要回避它。std::array