C++ c+中的字符串类赋值运算符重载+;

C++ c+中的字符串类赋值运算符重载+;,c++,string,overloading,destructor,operator-keyword,C++,String,Overloading,Destructor,Operator Keyword,我定义了自己的字符串类MyString。在我通过重载运算符=,将一个对象分配给另一个对象之前,一切都很正常。我知道问题在哪里,但不知道如何解决。有什么帮助吗 class MyString{ public: MyString( const MyString *strIni ); MyString( const char *str); ~MyString(); MyString& operator=( const MyString &str ); pr

我定义了自己的字符串类MyString。在我通过重载运算符=,将一个对象分配给另一个对象之前,一切都很正常。我知道问题在哪里,但不知道如何解决。有什么帮助吗

class MyString{
public:
    MyString( const MyString *strIni );
    MyString( const char *str);
    ~MyString();
    MyString& operator=( const MyString &str );
private:
    char *str;
}


MyString::MyString( const MyString *strIni ){
    this->str = new char[strlen(strIni->str)+1];
    strcpy(this->str,strIni->str) ;
};


MyString::MyString( const char *str){
    this->str = new char[ strlen(str) + 1 ];
    strcpy(this->str , str);
};

MyString::~MyString(){
    delete [] this->str ;
    cout << "successfully deleted..." << endl;
};


MyString& MyString::operator=( const MyString &str ){
    // temp obj holding the rhs
    MyString strTmp(str);
    // temp char pointer holding the rhs
    char *cTmp = strTmp.str;
    // temp obj holding this, later release this memory 
    strTmp.str = this->str ;
    // this holding rhs; assignment done.
    this->str = cTmp;
    return *this ;
};


int main(){
    {                                  // line 1
        MyString mystr1("string #1");  // line 2
        MyString mystr2("string #2");  // line 3
        mystr1 = mystr2;               // line 4
    }                                  // line 5
    return 0;
}
调用析构函数时,不会发生崩溃。但如果添加了打印输出成员函数,则会出现另一个问题:

void MyString::printout(){
    int str_size = strlen(this->str);
    cout << "string size: " << str_size << endl ;
    for( int i=0;i<str_size;i++ ){
        cout << *(this->str + i);
    }
}
看来mystr1是不正常的

有人能为我解释一下吗


谢谢你

这里的问题是声明

MyString strTmp(str);
在赋值运算符中,调用默认的隐式生成的复制构造函数。该构造函数将只复制指针,而不是创建新指针并复制字符串的内容


使用
MyString
指针的构造函数不是复制构造函数,复制构造函数将使用常量引用。如果您将使用指向MyString的指针的构造函数改为使用引用,那么它会工作得更好。

您显然必须修复运算符=()实现

#include <algorithm>

MyString& MyString::operator=( const MyString &rhs ) // (1)
{
    if (this != &rhs) // (2)
    {
        delete[] this->str; // (3)
        this->str = NULL;

        const int str_length = strlen(rhs.str);

        this->str = new char[str_length + 1];
        this->str[str_length] = '\0';
        std::copy(rhs.str, rhs.str + str_length, this->str); // (4)
    }

    return *this;
}

#include.

我当然希望这是学校作业或类似作业的可能副本,因为
std::string
已经足够好了。使用
MyString&MyString::operator=(const MyString&rhs){
相反。太多的
str
表示不同的东西。也许问题会更清楚。不要重新设计控制盘?这种错误就是为什么你应该使用现有的、有良好文档记录的和经过测试的类。在这种情况下,
std::string
。你可能需要调查
strdup
来复制assi中的字符串gnment操作符。@nyarlathotep是的,我刚刚意识到,这就是问题所在,我为它添加了一个答案。即使OP确实创建了一个深度复制复制构造函数,赋值操作符仍然会使用temp对象中的
char*
,该对象随后被删除,对吗?@nyarlathotep否,OP交换指针,所以它是旧的
this->str
被删除。啊,是的,错过了-可能是
std::swap
,以提高可读性;)只需注意:您的代码不提供“强”异常安全性:如果新字符抛出异常,
this->str
仍然指向未分配的空间(之前删除的内存).这就是为什么这里更倾向于使用swap成语的原因。仔细想想,它甚至没有提供基本的异常安全性,因为每当MyString被销毁时,
str
会再次被删除…@nyarlathotep True,这只是一种天真‎ 实现。复制交换习惯用法会更好。@nyarlathotep已编辑。谢谢您的评论。这是一个面试问题,不是作业。我实际上在使用运算符重载函数中的复制和交换。
string #1
string #2
after assignment...
string #2═²²²²
string #2
MyString strTmp(str);
#include <algorithm>

MyString& MyString::operator=( const MyString &rhs ) // (1)
{
    if (this != &rhs) // (2)
    {
        delete[] this->str; // (3)
        this->str = NULL;

        const int str_length = strlen(rhs.str);

        this->str = new char[str_length + 1];
        this->str[str_length] = '\0';
        std::copy(rhs.str, rhs.str + str_length, this->str); // (4)
    }

    return *this;
}