编译器默认提供赋值操作符重载实现,只不过是浅拷贝,深拷贝需要自己实现
#include <iostream>
#include <string>
using namespace std;
class Test
{
int* m_pointer;
public:
Test()
{
m_pointer = NULL;
}
Test(int i)
{
m_pointer = new int(i);
}
Test(const Test& obj)
{
m_pointer = new int(*obj.m_pointer);//申请内存,大小为m_pointer指向的空间的大小
}
Test& operator = (const Test& obj)
{
if( this != &obj )//确保不是自赋值,因为没有意义
{
delete m_pointer;
m_pointer = new int(*obj.m_pointer);
}
return *this;
}
void print()
{
cout << "m_pointer = " << hex << m_pointer << endl;
}
~Test()
{
delete m_pointer;
}
};
int main()
{
Test t1 = 1;
Test t2;
t2 = t1;//调用的是赋值操作符重载函数
t1.print();
t2.print();
return 0;
}
注:
Test t2 =t1;只会调用拷贝构造函数,而t2 = t1只会调用赋值操作符重载函数。这两种写法不是一个东西,一个是初始化,一个是赋值。
改写之前的数组类,增加赋值操作符重载:
IntArray& IntArray::operator = (const IntArray& obj)
{
if( this != &obj )
{
int* pointer = new int[obj.m_length];
if( pointer )
{
for(int i=0; i<obj.m_length; i++)
{
pointer[i] = obj.m_pointer[i];
}
m_length = obj.m_length;
delete[] m_pointer;
m_pointer = pointer;//深拷贝
}
}
return *this;
}
没有考虑赋值操作符重载函数的话,会出现以下问题(浅拷贝,两次释放相同内存空间,直接崩溃):
编译器给空的类放一些东西,四个函数的实现
c_str()是C++字符串库的函数,返回一个字符指针,代表C语言中的字符串
append()是在字符串末尾插入新的字符串
#include <iostream>
#include <string>
using namespace std;
int main()
{
string s = "12345";
const char* p = s.c_str();
cout << p << endl;
s.append("abced");
cout << p << endl;
return 0;
}
很显然插入不成功
string类内部有一个m_cstr指针,当初始化字符串时,这个指针便会指向一片堆空间。append()执行后,空间发生变化:重新申请空间,一起复制到新空间,旧的空间会被释放。此时p指针指向的是旧空间(已被释放),即p是个野指针。
#include <iostream>
#include <string>
using namespace std;
int main()
{
const char* p = "12345";
string s = "";
s.reserve(10);
// 不要使用 C 语言中的方式操作 C++ 中的字符串
for(int i=0; i<5; i++)
{
s[i] = p[i];
}
cout << s << endl;
return 0;
}
以上代码什么都不会打印
reserve(10):讲字符指针指向的堆空间大小变为10个字节
原因在于代表长度的内部m_length还是0,不要使用 C 语言中的方式操作 C++ 中的字符串
改进,这样就可以正常输出: