15指针成员的类的copy
一问题描述
默认的拷贝构造函数,和拷贝操作符函数,均执行按位copy。即如果将类 A = B ,且AB中有指针成员变量 , 则 A B 两个类的对象,在执行复制操作时,均指向同一处指针位置。若先对A进行析构,则A释放了指针空间。此时B无法访问指针变量。
注意点:
(1)如果为一个class添加了新的一个成员变量,那么需要同时修改copying函数。
(2)需要为子类编写copying函数。必须保证要很小心地复制其base class的成员变量。可以在子类的copying函数中,显式地调用其父类的copying函数。
但是不允许使用copy操作符函数调用 copy构造函数,两者不能互相调用,若想消除重复,可以使用一个公共函数,进行封装。
二 解决方法
方法1 深度复制
#include <iostream>
using namespace std ;
template <class T>
class Array
{
private:
T * data ;
unsigned size ;
public :
Array(unsigned arraySize):data(0) , size(arraySize)
{
size = arraySize ;
data = new T(size) ;
}
~Array()
{
if(data)
delete [] data ;
}
void setValue(int index , const T & value )
{
if(index < size)
data[index] = value ;
}
T getValue(int index)
{
if(index < size)
return data[index] ;
else
return T() ;
}
//解决一个拷贝构造函数和赋值函数的方法就是,将这两个函数设置为私有的
public :
Array<T>( Array<T> & copy):data(0) , size(copy.size) /**////要熟练使用默认参数的构造函数
{
if(size)
{
data = new T[size];
for(int i = 0 ; i < size ;i++)
setValue(i , copy.getValue(i)) ;
}
}
const Array<T> & operator=(const Array<T> & copy)
{
//首先判断要复制的地址是否一致
if(this == ©) //应该判断是否与地址相同
return *this ;
//首先判断,this指针所指向的对象的data是否为空,若不为空,需要进行删除缓冲区
if(data)
{
delete [] data ;
data = 0 ;
}
unsigned size = copy.size ;
if(size)
{
data = new T[size];
for(int i = 0 ; i < size ;i++)
setValue(i , copy.getValue(i)) ;
}
}
} ;
int main()
{
Array<char> A(10) ;
Array<char> B(A) ; // A和B 指向同一块内存,若是先执行对A的析构,则B指向的成员变量内存地址已经不存在,将出现错误
system("pause") ;
return 0 ;
} 二 引用计数
使用引用计数技术,若多个对象都使用了同一块内存,则只有所有的对象,都停止使用该对象的时候(即该对象的使用值为0), 该块内存才能被释放。
#include <iostream>
using namespace std ;
template <class T>
class Array
{
private:
T * data ;
unsigned size ;
int * count ; //作为引用计数 ,此处应该使用指针,使所有的对象,都指向(共享)同一块内存地址
public :
Array(unsigned arraySize):data(0) , count(new int) , size(arraySize)
{
*count = 1 ;
size = arraySize ;
data = new T(size) ;
}
~Array()
{
Release() ;
}
void setValue(int index , const T & value )
{
if(index < size)
data[index] = value ;
}
T getValue(int index)
{
if(index < size)
return data[index] ;
else
return T() ;
}
//解决一个拷贝构造函数和赋值函数的方法就是,将这两个函数设置为私有的
Array<T>( Array<T> & copy):data(copy.data) , count(copy.count) , size(copy.size) ///要熟练使用默认参数的构造函数
{
++(*count) ;
}
const Array<T> & operator=(const Array<T> & copy)
{
//首先判断要复制的地址是否一致
if(this == ©) //应该判断是否与地址相同
return *this ;
Release() ; //需要先删除原来占用的数据区间
data = copy.data ;
size = copy.size ;
count = copy.count ;
++(*count) ;
}
private :
void Release()
{
*(count) -- ;
if(*count == 0)
{
if(data)
{
delete [] data ;
data = 0 ;
}
delete count ; //删除分配的计数内存地址
count = 0 ;
}
}
} ;
int main()
{
Array<char> A(10) ;
Array<char> B(10) ; // A和B 指向同一块内存,若是先执行对A的析构,则B指向的成员变量内存地址已经不存在,将出现错误
B = A ;
system("pause") ;
return 0 ;
}