这是一个示例类:
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对象的析构函数,并且当指针被复制时,分配的内存消失了,因此指针无效。
为什么我要创建这样的对象:
赋值操作符是我试图避免删除它但从未调用的东西,不确定我是否正确。
无论如何,我如何制作自动myPeel = peelSource.getPeel();没有删除数据的工作?
答案 0 :(得分:1)
你写道:
我不想用新的分配果皮并返回一个指针,因为对于我喜欢剥离的容易性,一旦它超出范围就会自动销毁掉,而且,剥离有一个支架操作员,这个很多更好,无需先取消括号中的果皮。
您可以考虑以下内容。首先使用您想要的界面编写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;
}
};
使用此配置文件查看是否存在任何问题。由于NRVO,有一个相当不错的机会。
如果,由于某种原因,您发现无法通过有效的方式操纵peel
个对象,请考虑如下重构。首先,将所有重要部分移动到peel_imp
(再次避免使用指针和布尔标志)。
// "Heavy" peel stuff.
struct peel_imp
{
/* Hold here everything as regular value members, without
pointers or boolean flags indicating whether to delete, and
so forth.*/
};
然后,正如@EdHeal在评论中建议的那样,使用智能指针来保存实现。
struct peel
{
... operator[](...);
std::shared_ptr<peel_imp> m_imp;
};
再次使peel
个对象有效地进行值操作。
答案 1 :(得分:0)
为什么要在赋值时销毁对象并返回。它将成为无效指针并且无用。 更好的选择是使用移动构造函数/移动赋值运算符。