C++ 如何正确释放返回值

C++ 如何正确释放返回值,c++,memory-leaks,return-value,C++,Memory Leaks,Return Value,我需要为我的类创建一个+运算符,我是这样做的: class CDoubleString{ public: string textA=""; string textB=""; CDoubleString(string x,string y) : textA(x),textB(y){} CDoubleString & operator + (const CDoubleString & y){ CDoubleString * n=new CDou

我需要为我的类创建一个+运算符,我是这样做的:

class CDoubleString{
public:
   string textA="";
   string textB="";
   CDoubleString(string x,string y) : textA(x),textB(y){}

   CDoubleString & operator + (const CDoubleString & y){
       CDoubleString * n=new CDoubleString(textA,textB);
       n->textA+=y.textA;
       n->textB+=y.textB;
       delete n;
       return *n;
   }
}
看起来它像预期的那样工作,但是我发现释放内存有问题。在我归还它的那一刻,它可能已经是别的东西了。所以这是未定义的行为,对吗?
如何避免这种情况

所以这是未定义的行为,对吗

如何避免这种情况

有几种方法

  • 按值返回

    CDoubleString operator + (const CDoubleString & y){
        CDoubleString n(textA,textB);
        n.textA+=y.textA;
        n.textB+=y.textB;
        return n;
    }
    
  • 返回一个
    std::unique\u ptr

    std::unique_ptr<CDoubleString> operator + (const CDoubleString & y){
        std::unique_ptr<CDoubleString> n = std::make_unique<CDoubleString>(textA,textB);
        n->textA+=y.textA;
        n->textB+=y.textB;
        return n;
    }
    
    std::唯一的ptr运算符+(常量CDoubleString&y){
    std::unique_ptr n=std::make_unique(textA,textB);
    n->textA+=y.textA;
    n->textB+=y.textB;
    返回n;
    }
    
  • 我更喜欢你的第一种变体。对于大多数现代编译器,您可以依赖RVO和copyelistion,因此不必担心额外的副本

    所以这是未定义的行为,对吗

    如何避免这种情况

    有几种方法

  • 按值返回

    CDoubleString operator + (const CDoubleString & y){
        CDoubleString n(textA,textB);
        n.textA+=y.textA;
        n.textB+=y.textB;
        return n;
    }
    
  • 返回一个
    std::unique\u ptr

    std::unique_ptr<CDoubleString> operator + (const CDoubleString & y){
        std::unique_ptr<CDoubleString> n = std::make_unique<CDoubleString>(textA,textB);
        n->textA+=y.textA;
        n->textB+=y.textB;
        return n;
    }
    
    std::唯一的ptr运算符+(常量CDoubleString&y){
    std::unique_ptr n=std::make_unique(textA,textB);
    n->textA+=y.textA;
    n->textB+=y.textB;
    返回n;
    }
    
  • 我更喜欢你的第一种变体。对于大多数现代编译器,您可以依赖RVO和copyelistion,因此不必担心额外的副本

    所以这是未定义的行为,对吗

    是的,但不是你想的那样。您正在返回对已删除对象的引用,该引用无效,并且具有未定义的行为。但是“它可能已经是其他的东西”适用于调用方,因为实际上是调用方最终会从死引用中读取,即使您延迟删除对象,这也可能会导致问题:您可能仍然延迟得不够

    如何避免这种情况

    按值返回可能是最简单的

    CDoubleString operator + (const CDoubleString & y){
        CDoubleString n(textA,textB);
        n.textA+=y.textA;
        n.textB+=y.textB;
        return n;
    }
    
    所以这是未定义的行为,对吗

    是的,但不是你想的那样。您正在返回对已删除对象的引用,该引用无效,并且具有未定义的行为。但是“它可能已经是其他的东西”适用于调用方,因为实际上是调用方最终会从死引用中读取,即使您延迟删除对象,这也可能会导致问题:您可能仍然延迟得不够

    如何避免这种情况

    按值返回可能是最简单的

    CDoubleString operator + (const CDoubleString & y){
        CDoubleString n(textA,textB);
        n.textA+=y.textA;
        n.textB+=y.textB;
        return n;
    }
    

    我推荐重载运算符的规范实现。特别是。请注意返回值与代码之间的差异。@Someprogrammerdude我确实知道这个引用并偶尔使用它,但我不知道这个部分。谢谢。我推荐重载运算符的规范实现。特别是。请注意返回值与代码之间的差异。@Someprogrammerdude我确实知道这个引用并偶尔使用它,但我不知道这个部分。谢谢