简体   繁体   English

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

[英]string class assignment operator overloading in c++

I defined my own string class, MyString. 我定义了自己的字符串类MyString。 Everything works well until I assign one object to the other by the overloaded operator=. 一切正常,直到我通过重载operator =将一个对象分配给另一个对象。 I know where the problem is but I don't know how to fix it. 我知道问题在哪里,但我不知道如何解决它。 Any helps? 有帮助吗?

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;
}

The problem of the code is: at line4, after the assignment the pointer in two objects mystr1 and mystr2 both point the same string "string #2". 代码的问题是:在第4行,在赋值后,两个对象mystr1和mystr2中的指针都指向相同的字符串“string#2”。 When the program jump out of the brackets at line 5, the destructors are automatically called by sequence: mystr2 and then mystr1. 当程序跳出第5行的括号时,析构函数会自动按顺序调用:mystr2然后是mystr1。 After mystr2 is destructed, the memory of "string #2" has been released. 在mystr2被破坏后,“string#2”的内存已被释放。 When the destructor of mystr1 is trying to release non-existing memory, the program crashed. 当mystr1的析构函数试图释放不存在的内存时,程序崩溃了。

Anybody can help me to fix the overloading member function. 任何人都可以帮我修复重载成员函数。 When I assign mystr1 = mystr2, i can create a new string instead of making the two pointers pointing the same string. 当我指定mystr1 = mystr2时,我可以创建一个新的字符串,而不是让两个指针指向同一个字符串。

Thanks a lot!! 非常感谢!!



Updates for further questions...... thank tons!! 更新进一步的问题......谢谢吨!

actually, i am using copy-and-swap in the overloading function. 实际上,我在重载函数中使用了copy-and-swap。 based on @Mateusz Kołodziejski 's advice, i modified it: 根据@MateuszKołodziejski的建议,我修改了它:

MyString& MyString::operator=( const MyString &rhs ){
    if( this != &rhs ){
        // copy using constructor
        MyString strTmp(rhs) ;
        // swap        
        char *cTmp = strTmp.str;
        // strTmp will be destructed, thus the memory in this will be released
        strTmp.str = this->str ;
        // size of rhs
        const int str_size = strlen(rhs.str);
        this->str = new char[str_size+1];
        copy(rhs.str,rhs.str+str_size,this->str);
    }
    return *this ;
};

when the destructors are called, no crash. 当析构函数被调用时,不会崩溃。 But if a printout member function is added, there seems another problem: 但是如果添加了打印输出成员函数,则会出现另一个问题:

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);
    }
}

in main function: 在主要功能:

int main(){
    {                                  
        MyString mystr1("string #1");  
        MyString mystr2("string #2");  
        mystr1.printout();
        mystr2.printout();
        mystr1 = mystr2;  
        cout << "after assignment: " << endl;
        mystr1.printout();
        mystr2.printout();             
    }                                  
return 0;
}

the results are: 结果是:

string #1
string #2
after assignment...
string #2═²²²²
string #2

seems that mystr1 is not normal... 似乎mystr1不正常......

anybody can explain this for me? 谁能为我解释一下?

Thank tons!! 谢谢吨!!

You obviously have to fix your operator=() implementation. 你显然必须修复你的operator =()实现。

#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;
}

1) Use "rhs" (right-hand-side) instead of "str" for your variable name to avoid ambiguity. 1)使用“rhs”(右侧)代替“str”作为变量名,以避免歧义。

2) Always check if your object is not being assigned to itself. 2)始终检查您的对象是否未分配给自己。

3) Release the old allocated memory before allocating new. 3)在分配新内存之前释放旧分配的内存。

4) Copy over the contents of rhs to this->str, instead of just redirecting pointers. 4)将rhs的内容复制到this-> str,而不是仅仅重定向指针。

EDIT: 编辑:

Added this->str = NULL; 添加了这个 - > str = NULL; to avoid double deletion on possible exception from new, and later object deconstruction. 避免对新的和后来的对象解构可能的异常进行双重删除。

This is a naïve implementation - you have to be aware that new can throw an exception. 这是一个天真的实现 - 您必须意识到new可以抛出异常。 Copy-swap idiom would be better here as suggested by @nyarlathotep and described here: Copy-and-swap . 复制交换习语在这里会更好,正如@nyarlathotep所建议的那样,并在此处描述: 复制和交换

The problem here is that with the declaration 这里的问题是声明

MyString strTmp(str);

in the assignment operator, you call the default implicitly generated copy-constructor. 在赋值运算符中,您调用默认隐式生成的复制构造函数。 And that constructor will simply just copy the pointer, not create a new pointer and copy the contents of the string. 并且该构造函数将只是复制指针,而不是创建新指针并复制字符串的内容。

The constructor you have taking a MyString pointer is not a copy-constructor, a copy-constructor would take a constant reference instead. 使用MyString指针的构造函数不是复制构造函数,复制构造函数将采用常量引用 If you change your constructor taking a pointer to MyString to take a reference instead, then it will work better. 如果您更改构造函数,并使用指向MyString的指针来取代引用,那么它将更好地工作。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM