经典问题解析三
1、关于赋值的疑问
什么时候需要重载赋值操作符?编 译器是否提供默认的赋值操作?
- 编译器为每个类默认重载了赋值操作符
- 默认的赋值操作符仅完成浅拷贝
- 当需要进行深拷贝时必须重载赋值操作符
- 赋值操作符与拷贝构造函数有相同的存在意义
2、代码实例
如何解决?
//36-1.cpp
#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));
}
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 test1 = 1;
Test test2;
test2 = test1;
test2 = test2;
test1.print();
test2.print();
return 0;
}
//compile,run
$ ./a.out
m_pointer= 0x20c4e70
m_pointer= 0x20c4e90
3、完善数组类
//IntArray.h
#ifndef _INTARRAY_H_
#define _INTARRAY_H_
class IntArray
{
private:
int m_legth;
int* m_pointer;
IntArray(int len);
IntArray(const IntArray& obj);
bool construct();
public:
int length();
bool get(int index, int& value);
bool set(int index, int value);
static IntArray* NewInstance(int length);
//void free();
int& operator [] (int index);
IntArray& operator = (const IntArray& obj);
IntArray& self();
~IntArray();
};
#endif// _INTARRAY_H_
//IntArray.cpp
#include "IntArray.h"
#include<iostream>
#include<string>
using namespace std;
IntArray::IntArray(int len)
{
m_legth = len;
}
bool IntArray::construct()
{
bool ret = true;
m_pointer = new int[m_legth];
if(m_pointer)
{
for(int i = 0; i < m_legth; i++)
{
m_pointer[i] = 0;
}
}
else
{
ret = false;
}
return ret;
}
IntArray* IntArray::NewInstance(int length)
{
IntArray* ret = new IntArray(length);
if(!(ret && ret->construct()))
{
delete ret;
ret = 0;
}
return ret;
}
int IntArray::length()
{
return m_legth;
}
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;
}
ret;
}
int& IntArray::operator [] (int index)
{
return m_pointer[index];
}
IntArray& IntArray::self()
{
return *this;
}
IntArray& IntArray::operator = (const IntArray& obj)
{
if( this != &obj )
{
int* pointer = new int[obj.m_legth];
if(pointer)
{
for(int i = 0; i < obj.m_legth; i++)
{
pointer[i] = obj.m_pointer[i];
}
m_legth = obj.m_legth;
delete[] m_pointer;
m_pointer = pointer;
}
}
return *this;
}
IntArray::~IntArray()
{
delete[] m_pointer;
}
//main.cpp
#include "IntArray.h"
#include<iostream>
#include<string>
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;
}
4、一般性原则
重载复制操作符,必然需要实现深拷贝!!
5、知识点
6、关于string的疑问
下面的代码输出什么?为什么?
string s = "123456";
const char* p =s.c_str();//此处C语言混用,出现野指针
cout << p << endl;
s.append("abcde");//P成为了野指针
cout << p << endl;
要么C语言编程,严么C++编程,千万不能混用!!
7、关于string的另一个疑问
下面的程序输出什么?为什么?
const char* p = "12345";
string s = "";
s.reserve(10);
for(int i=0; i<5; i++)
{
s[i] = p[i];
}
if( !s.empty() )
{
cout << s << endl;
}
#include<iostream>
#include<string>
using namespace std;
int main()
{
#if 0
//C语言与C++混用
const char* p = "12345";
string s = "";
s.reserve(10);
for(int i=0; i<5; i++)
{
s[i] = p[i];
}
for(int i=0; i<5; i++)
{
cout << s[i] << endl;
}
cout << s << endl;
#else
const string p = "12345";
string s = "";
s = p;
cout << s << endl;
#endif
return 0;
}
//compile,run
$ ./a.out
12345
8、小结
- 在需要进行深拷贝的时候必须重载赋值操作符
- 赋值操作符和拷贝构造函数有同等重要的意义
- string类通过一个数据空间保存字符数据
- string类通过一个成员变量保存当前字符串的长度
- C++开发时尽量避开C语言中惯用的编程思想