---- 整理自狄泰软件唐佐林老师课程
文章目录
1. 关于赋值的疑问
- 什么时候需要重载赋值操作符?编译器是否提供默认的赋值操作?
- 编译器为每个类 默认重载了赋值操作符
- 默认的赋值操作符 仅完成 浅拷贝
- 当需要进行 深拷贝 时 必须重载赋值操作符
- 赋值操作符与拷贝构造函数有相同的存在意义
1.1 编程实验:默认赋值操作符重载
#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);
}
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;
}
1.2 问题分析
- 重载赋值操作符,必然需要实现深拷贝:
#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& t) {
m_pointer = new int(*t.m_pointer);
}
Test& operator=(const Test& t) {
if (this != &t) {
delete m_pointer;
m_pointer = new int(*t.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;
}
1.3 一般性原则
重载 赋值操作符,必然需要实现 深拷贝
1.4 编程实验:数组类的优化
#ifndef _INTARRAY_H_
#define _INTARRAY_H_
class IntArray
{
private:
int m_length;
int* m_pointer;
IntArray(int len);
bool construct();
public:
static IntArray* NewInstance(int len);
int length();
bool get(int index, int& value);
bool set(int index, int value);
int& operator[](int index);
IntArray& operator=(const IntArray& obj);
IntArray& self();
~IntArray();
};
#endif
#include "IntArray.h"
IntArray::IntArray(int len) { m_length = len; }
bool IntArray::construct() {
bool ret = true;
m_pointer = new int[m_length];
if (m_pointer) {
for(int i = 0; i < m_length; i++) {
m_pointer[i] = 0;
}
} else {
ret = false;
}
return ret;
}
IntArray* IntArray::NewInstance(int len) {
IntArray* ret = new IntArray(len);
if (ret != nullptr && ret->construct() != true) {
delete ret;
ret = 0;
}
return ret;
}
int IntArray::length() { return m_length; }
bool IntArray::get(int index, int& value) {
bool ret = (0 <= index) && (index < length());
if( ret ) {
value = m_pointer[index];
}
return ret;
}
bool IntArray::set(int index, int value) {
bool ret = (0 <= index) && (index < length());
if( ret ) {
m_pointer[index] = value;
}
return ret;
}
int& IntArray::operator [] (int index) {
return m_pointer[index];
}
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;
}
IntArray& IntArray::self() {
return *this;
}
IntArray::~IntArray() { delete[] m_pointer; }
#include <iostream>
#include <string>
#include "IntArray.h"
using namespace std;
int main() {
IntArray* a = IntArray::NewInstance(5);
IntArray* b = IntArray::NewInstance(10);
if( a && b ) {
IntArray& array = a->self();
IntArray& brray = b->self();
cout << "array.length() = " << array.length() << endl;
cout << "brray.length() = " << brray.length() << endl;
array = brray;
cout << "array.length() = " << array.length() << endl;
cout << "brray.length() = " << brray.length() << endl;
}
delete a;
delete b;
return 0;
}
1.5 编译器默认提供的函数
左边看起来是个空类,但实际编译器会 默认提供如上 4 个函数。
2. 关于 string 的疑问 1
- 下面的代码输出什么?为什么?
2.1 编程实验:字符串问题 1
#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;
}
2.2 问题分析
- string 对象内部维护了一个指向数据的 char* 指针,这个指针可能在程序运行的过程中发生改变
3. 关于 string 的疑问 2
- 下面的代码输出什么?为什么?
3.1 编程实验:字符串问题 2
#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;
}
3.2 问题分析
- 修改如下:
#include <iostream>
#include <string>
using namespace std;
int main()
{
const char* p = "12345";
string s = "";
s.reserve(10);
s = p;
cout << s << endl;
return 0;
}
4. 小结
- 在需要进行深拷贝的时候必须重载赋值操作符
- 赋值操作符和拷贝构造函数有同等重要的意义
- string 类通过一个数据空间保存字符数据
- string 类通过一个成员变量保存当前字符串的长度
- C++ 开发时尽量避开 C 语言中惯用的编程思想