c++中的字符串类赋值运算符重载
string class assignment operator overloading in c++
我定义了自己的字符串类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;
}
代码的问题是:在第4行,在赋值之后,两个对象mystr1和mystr2中的指针都指向同一个字符串"string#2"。当程序从第5行的括号中跳出来时,析构函数会自动按顺序调用:mystr2,然后是mystr1。mystr2被破坏后,"字符串#2"的内存被释放。当mystr1的析构函数试图释放不存在的内存时,程序崩溃了。
任何人都可以帮助我修复重载成员函数。当我指定mystr1=mystr2时,我可以创建一个新的字符串,而不是让两个指针指向同一个字符串。
非常感谢!!
进一步问题的更新。。。。。。谢谢tons!!
实际上,我在重载函数中使用了复制和交换。根据@Mateusz Koł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 ;
};
当调用析构函数时,没有崩溃。但是,如果添加打印输出成员功能,似乎还有另一个问题:
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);
}
}
主要功能:
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;
}
结果是:
string #1
string #2
after assignment...
string #2═²²²²
string #2
似乎mystr1不正常。。。
有人能为我解释一下吗?
谢谢!!
您显然必须修复您的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] = ' ';
std::copy(rhs.str, rhs.str + str_length, this->str); // (4)
}
return *this;
}
1) 使用"rhs"(右手边)而不是"str"作为变量名,以避免歧义。
2) 请始终检查对象是否未分配给其自身。
3) 先释放已分配的旧内存,然后再分配新内存。
4) 将rhs的内容复制到此->str,而不仅仅是重定向指针。
编辑:
添加了这个->str=NULL;以避免对新的、后来的对象解构中可能出现的例外进行双重删除。
这是一个幼稚的实现——你必须意识到new可能会抛出异常。复制交换习语在这里会更好,正如@nyarlathotep所建议的,并在这里描述的:复制和交换。
这里的问题是使用声明
MyString strTmp(str);
在赋值运算符中,您可以调用默认的隐式生成的复制构造函数。该构造函数只会复制指针,而不会创建新指针并复制字符串的内容。
采用MyString
指针的构造函数是而不是。复制构造函数将采用常量引用代替。如果您更改构造函数,将指向MyString
的指针改为引用,那么它会更好地工作。
- 使用赋值运算符重载从类中返回jobject
- 赋值运算符重载和自赋值
- C++ 指针赋值运算符重载(不仅是对象赋值,还有指针赋值)
- 赋值运算符重载在通过指针访问时不调用
- "return *this"赋值运算符重载
- 赋值运算符重载 c++ 的返回值
- 在对类对象的赋值进行链接时获取垃圾值,使用按值返回类对象的赋值运算符重载
- 在c++中的赋值运算符重载方法中删除旧的动态分配内存
- 复合赋值运算符重载
- 对象的动态内存和赋值运算符重载
- c++中的赋值运算符重载
- c++赋值运算符重载
- 如何通过赋值运算符重载将一个列表复制到另一个列表上?C++
- 赋值运算符重载和无效内存
- 赋值运算符重载 -- 错误 C2440:'==':无法从 'A<T> *' 转换为 'A<T> *const '
- 为什么内存泄漏只发生在赋值运算符重载的情况下,而不是在复制构造函数中,以及复制和交换习惯用法如何解决它
- 内存泄漏,使赋值运算符重载、新建、删除和C++
- C++中的效率和赋值运算符重载
- 赋值运算符重载/检索功能
- 为什么在赋值运算符重载中返回引用