C++ 如何避免在分配/返回时销毁对象
这是一个示例类:C++ 如何避免在分配/返回时销毁对象,c++,C++,这是一个示例类: struct peel { int* p; bool nodelete; peel() { nodelete = false; } ~peel() { if (!nodelete) delete p; } peel& operator=(const peel& other) { p = other.p; nodelete = true;
struct peel {
int* p;
bool nodelete;
peel() {
nodelete = false;
}
~peel() {
if (!nodelete) delete p;
}
peel& operator=(const peel& other) {
p = other.p;
nodelete = true;
}
};
struct banana {
peel getPeel() {
peel ret;
ret.p = new int();
return ret;
}
};
所以当我打电话的时候
banana peelSource;
auto myPeel = peelSource.getPeel();
我不能使用myPeel,因为在返回和赋值之间的某个地方调用了peel对象的析构函数,并且在复制指针时,分配的内存消失了,因此指针无效
为什么要创建这样的对象:
peel
。将所有内容作为常规值成员保存,不包含指针、表示不删除的布尔标志等
struct peel
{
/* Hold here everything as regular value members, without
pointers or boolean flags indicating whether to delete, and
so forth.*/
// Here's your brackets operator.
... operator[](...);
};
现在就用这个
struct banana
{
peel getPeel() {
peel ret;
...
return ret;
}
};
配置文件以查看使用此配置文件时是否存在任何问题。有一个相当好的机会不会有,因为
如果由于某种原因,你发现你不能有效地操纵<代码>剥离>代码>对象,那么考虑重构如下。首先,将所有重型零件移动到
peel_imp
(再次避免指针和布尔标志)
然后,正如@EdHeal在评论中所建议的,使用智能指针来保存实现
struct peel
{
... operator[](...);
std::shared_ptr<peel_imp> m_imp;
};
struct-peel
{
…运算符[](…);
std::共享ptr m_imp;
};
再次使
peel
对象有效地进行值操作。为什么要在赋值和返回时销毁对象。这将是无效的指针和无用的。
更好的选择是使用移动构造函数/移动赋值运算符。我喜欢注定会发生内存泄漏的代码。请仔细阅读智能指针,了解您违反了该操作。您有一个自定义析构函数和自定义赋值运算符,但没有自定义复制构造函数。
return
语句使用复制构造函数将peel
复制到调用方。默认的自定义副本构造函数是浅层副本。这意味着原件和副本都具有相同的值p
,并且它们都具有nodelete=false
,这意味着两者都将在销毁时尝试删除p
。peel
首先销毁,删除p
。这就给副本留下了一个悬空的指针。按照您设计代码的方式,它将以一个悬空的指针结束。您可能想让赋值操作符(和复制构造函数)将另一个对象的nodelete
设置为false。这会起作用,但有更好的解决方案。你的解释根本不能令人信服地说明为什么你想在这个任务中使用动态分配。@M.M我完全同意,但我不知道我的答案中包含的代码的正确性是否依赖于省略。我的观点只是关于表现。哦,我明白你的意思。谢谢你的评论。答案并非如此,但我明白为什么答案并不明显。将更新。
struct peel
{
... operator[](...);
std::shared_ptr<peel_imp> m_imp;
};