gpt4 book ai didi

c++ - CArray 不会在内存重新分配时调用复制构造函数,现在怎么办?

转载 作者:可可西里 更新时间:2023-11-01 10:09:44 25 4
gpt4 key购买 nike

假设我有一个类需要调用复制构造函数来正确复制:

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. 返回非常量引用是 operator= 的标准,因为它符合原始类型的语义。
  2. 按值传递参数是制作原始拷贝的最简单方法,并保证如果复制构造函数失败,此对象不会受到影响。
  3. 对 swap 的调用以永远不会抛出异常的方式将传入的拷贝与此对象进行切换,从而以完全异常安全的方式影响分配。

在这种情况下,只分配数字会更简单,但我习惯性地以这种方式实现我的所有分配,以避免如果 future 的维护者让复制抛出异常成为可能,我会被抓到。

关于c++ - CArray 不会在内存重新分配时调用复制构造函数,现在怎么办?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2928369/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com