问题1:
什么时候需要重载赋值操作符?
编译器是否提供默认的赋值操作符?
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);
}
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();
// C 语言中有自我赋值的,C++为了兼容
int i = 0;
i = i
return 0;
}
实现深拷贝四个注意点(赋值操作符)
- 返回值为引用
- 参数是 const 的引用关系
- 自赋值的情况(这个只是为了兼容 C 里面用的)
- 返回自己 *this
一般性原则:
如果要重写赋值操作符,需要实现深拷贝(浅拷贝会占用相同的内存,深拷贝会去堆里面从新申请内存)
问题2:(面试题)
class Test
{
};
// 这个类并不是成员函数,编译器会默认提供如下函数
class Test
{
Test();
Test(const Test& t);
Test& operator = (const Test& t);
~Test();
};
问题3_1:
分析下面的代码
string s = "12345";
const char* p = s.c_str();
// c_str():生成一个const char*指针,指向以空字符终止的数组。
cout << p << endl;
s.append("abced"); // p 成为了野指针
cout << p << endl;
输出结果: 为什么输出的结果相同?
分析:
string 对象内部维护了一个指向数据的 char* 指针,这个指针可能在程序运行的过程中发送变化
问题3_2:
分析下面的代码
const char* p = "12345";
string s = "";
s.reserve(10);
// 不要使用 C 语言中的方式操作 C++ 中的字符串
for(int i=0; i<5; i++)
{
s[i] = p[i];
}
if( !s.empty())
{
cout << s << endl;
}
输出: 为空
分析:
m_length 一直为空。
//改进上面的代码
const string p = "12345";
string s = " ";
s = p;
cout << s << endl;
不要混合 C 和 C++ 的编程思想!!
小结
- 在需要进行深拷贝的时候必需重载赋值操作符
- 赋值操作符和拷贝构造函数有同等重要的意义
- string 类通过一个数据空间保持字符数据
- string 类通过一个成员变量保存当前字符串的长度
- C++ 开发时尽量避免 C 语言中惯用的编程思想