return一个类对象的时候 调用了复制构造函数 之后再调用析构函数 为何返回的是析构之后的值?

朋友实现了一个String类 其实问题不少 比如NULL传入strlen等,但是最大的问题是很奇怪 main函数执行到S=S1+S2时 单步调试发现加法运算符重载函数中那个类对象temp在执行到return时 作为参数 传给了复制构造函数 这个正常 按理说之后temp会被析构 然后函数的返回值应当是之前被复制构造函数创建的无名临时对象的值,但很奇怪 调试信息说明 返回的居然是temp被析构之后的值。。。

找了很多的资料也没明白 还望高人指点

#define _CRT_SECURE_NO_WARNINGS
#define FILE_BUFFER_LENGTH 30000 

#include<iostream>
#include<cstring>
using namespace std;

class CMyString {
    friend std::ostream& operator<<(std::ostream& out, CMyString& rhs);
    //friend std::istream& operator>>(std::istream& in, CMyString& rhs);
public:
    CMyString() {
        buf = NULL;
    }
    CMyString(const char* rhs) {
        buf = new char[strlen(rhs) + 1];
        strcpy(buf, rhs);
    }
    CMyString(const CMyString& rhs)
    {
        buf = new char(strlen(rhs.buf) + 1);
        buf = rhs.buf;
    }
    ~CMyString() {
        cout << "called" << endl;
        if (buf != NULL) {
            delete[]buf;
        }
    }
    CMyString& operator=(const CMyString& rhs);
    CMyString operator+(const CMyString& rhs);
private:
    char* buf;
};

ostream& operator<<(std::ostream& out, CMyString& rhs) {
    out << rhs.buf;
    return out;
}

CMyString& CMyString::operator=(const CMyString& rhs) {
    if (this != &rhs) {
        if (buf != NULL) delete[]buf;
        buf = new char[strlen(rhs.buf) + 1];
        strcpy(buf, rhs.buf);
    }
    return *this;
}

CMyString CMyString::operator+(const CMyString & rhs) {
    CMyString temp;
    temp.buf = new char[strlen(buf) + strlen(rhs.buf) + 1];
    strcpy(temp.buf, buf);
    strcat(temp.buf, rhs.buf);
    return temp;
}

int main() {
    CMyString   S1("Good"), S2(" morning"), S3(" evening"), S;

    S = S1 + S2;
    cout << S << endl;
    //S.~CMyString();
    system("pause");
    return 0;
}

有两个部分错误:

    CMyString(const CMyString& rhs)
    {
        buf = new char(strlen(rhs.buf) + 1);
        buf = rhs.buf;
    }

第一个是这个地方

这个函数中 new char(strlen(rhs.buf) + 1); 应该是 new char[strlen(rhs.buf) + 1];

第二个是这个地方

buf = rhs.buf; 这一句去掉 加上strcpy(buf, rhs.buf);
改正后的代码
    CMyString(const CMyString& rhs)
    {
        buf = new char[strlen(rhs.buf) + 1];
        strcpy(buf, rhs.buf);
        //buf = rhs.buf;
    }
  • 这样就正确了,使用上个对象的buf ,而那个对象的buf被析构掉了.
内部原理:
S = S1+S2;

MyString tmp;
S1.operator+(S2,tmp)
S = tmp;

返回MyString ,其实是以引用方式传入了一个临时变量,然后返回值放在这个变量里,返回之后再赋值给显示调用 operator = 的那个变量,就是S.