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对象的析构函数,并且在复制指针时,分配的内存消失了,因此指针无效

为什么要创建这样的对象:

  • 在我的实际课程中,香蕉包含了很多创建果皮所必需的信息,总的来说,让香蕉创建果皮更容易
  • 我不想用new分配一个peel并返回一个指针,因为对于一个peel,我喜欢它一旦超出范围就会自动被破坏,而且peel有一个括号操作符,它比使用括号操作符要好得多,不必首先取消对括号中的peel的引用
  • 赋值运算符是我试图避免删除的东西,但它从未调用过,不确定我是否做对了

    无论如何,如何使auto myPeel=peelSource.getPeel();在没有删除数据的情况下工作?

    您写:

    我不想用new分配一个peel并返回一个指针,因为对于一个peel,我喜欢它一旦超出范围就会自动被破坏,而且peel有一个括号操作符,它比使用括号操作符要好得多,不必首先取消对括号中的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;
    };