假设我有一个需要复制构造函数的类来创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; }
无论如何,这通常是一个好主意,以避免复制构建和分配之间的不一致的行为。
仅供参考,上述代码使用惯用方法来实现强大的异常安全保证的分配语义:
operator=
的标准,因为它匹配基本类型的语义。 在这种情况下,分配数字会更简单,但是我习惯性地按照这种方式执行所有的分配任务,以防未来的维护人员通过复制来抛出异常。
或者是否认为使用CArray是一个坏主意?
是的,这是一个非常糟糕的主意。 尽可能使用std::vector
。