CArray不调用内存重新分配的拷贝构造函数,现在呢?

假设我有一个需要复制构造函数的类来创build正确的副本:

struct CWeird { CWeird() { number = 47; target = &number; } CWeird(const CWeird &other) : number(other.number), target(&number) { } const CWeird& operator=(const CWeird &w) { number = w.number; return *this; } void output() { printf("%d %d\n", *target, number); } int *target, number; }; 

现在麻烦的是,当重新分配内存时,CArray不会在其元素上调用复制构造函数(例如,从旧内存到新的内存只有memcpy),例如这个代码

 CArray<CWeird> a; a.SetSize(1); a[0].output(); a.SetSize(2); a[0].output(); 

结果是

 47 47 -572662307 47 

我不明白 为什么std :: vector可以正确地复制相同的对象,并且CArray不能? 这里有什么教训? 我应该只使用不需要显式拷贝构造函数的类吗? 或者是否认为使用CArray是一个坏主意?

被复制的指针仍然指向原来的数字,这个数字已经不存在了,因为数组已经被重新分配了。

我猜测CArray使用分配而不是复制构造。 定义一个赋值操作符来查看是否修复它:

 CWeird& operator=(CWeird w) { swap(w); return *this; } void swap(CWeird& w) { int t = number; number = w.number; w.number = t; } 

无论如何,这通常是一个好主意,以避免复制构建和分配之间的不一致的行为。

仅供参考,上述代码使用惯用方法来实现强大的异常安全保证的分配语义:

  1. 返回非const引用是operator=的标准,因为它匹配基本类型的语义。
  2. 按值传递参数是复制原始文件的最简单方法,并且保证如果复制构造函数失败,这个对象不会受到影响。
  3. 对swap的调用以一种永远不会抛出异常的方式切换传入的副本,从而以完全异常安全的方式执行分配。

在这种情况下,分配数字会更简单,但是我习惯性地按照这种方式执行所有的分配任务,以防未来的维护人员通过复制来抛出异常。

或者是否认为使用CArray是一个坏主意?

是的,这是一个非常糟糕的主意。 尽可能使用std::vector