如果有一个对象,让我们称它为o
,还有两个数组typeo *a,*b;
如果我将o
分配给数组a
和数组b
,那么delete[] b
如果我尝试在中访问o或o会发生什么?例如:
struct name{int a;}
name *a = new name[1];
name *b = new name[1];
name o;
a[0] = o;
b[0] = o;
delete[] b;
a[0]; // what happens here?
如果只定义inta[1]
,则不在堆中分配内存,因此无需删除。
否则,如果按以下方式创建数组:CCD_ 8,您必须删除为delete [] a;
通过考虑以上两种情况,如果您为b和a分配了内存,则在删除b后可以安全地访问"a"。
在这个例子中没有任何问题。a[0]
和b[0]
是位于不同存储位置的不同对象,销毁其中一个对另一个没有影响。
new
是在转移注意力;以下代码的工作方式相同:
name o;
name a = o;
{
name b = o;
}
a;
name
具有值语义,也就是说,按值复制它会创建一个完全不同的副本。诸如int
之类的内置类型也都具有值语义。
只有当o
没有值语义时,此代码才会遇到问题;例如,如果它包含一个资源句柄,而不包含用于复制资源句柄的复制构造函数和赋值运算符代码。
然后复制o
会在该资源上生成两个具有相同句柄的对象,如果o
的析构函数释放了该资源,则会留下一个悬空副本。
为了避免这些问题,通常建议将所有类设计为具有值语义。如果类对不可重复的资源有一个句柄,则该类应禁用其复制构造函数和赋值运算符,以防止不必要的复制。事实上,资源句柄应该由为资源句柄设计的类持有。
这有时被称为"三规则"(或自C++11以来,"五规则"或"零规则")。