您的位置:首页 > 编程语言 > C语言/C++

C++浅拷贝的另一种实现方式

2016-12-11 21:38 211 查看
C++的浅拷贝,虽然编译器已经默认帮我们实现了,但是作为一个技术人员应该要具备有最基本的“黑客精神”,说到C++浅拷贝的实现,大家第一反应就是通过拷贝构造函数实现成员变量的直接赋值。也就是如下的代码:

class A
{
public:
A()
{
arrayA = new int [size];//内存分配
for( size_t i = 0;i<size;i++)
{
arrayA[i] = i;
}
~A()
{
delete arrayA;
}
A(const A& object)//复制构造函数
{
this->arrayA = object.arrayA;//成员变量直接复制,实现浅拷贝
}
private:
const size_t size= 40;
int *arrayA;
}


当然写到这里,如果就是这么简单的话就没有必要写这篇博客了,浅拷贝也叫按位拷贝,就是将一个对象的内存空间的内容远远本本拷贝过去。多说一点因为对象的指针成员所指向的内存不属于该对象的内容,不占用对象的内存空间,所以浅拷贝不会将对象中指针成员所指向的内存复制过去;就好像上面的例子如果执行浅拷贝,那么拷贝的只是arrayA本身,而它所指向的40个整形的内存空间是不会被拷贝过去的;因此浅拷贝的源对象如果被析构之后,复制对象的中的指针成员就会成为空悬指针(Dangling Pointer)

扯远了,那按位拷贝从语义上来说就是,在内存空间中以byte为单位将内存复制到另一个内存空间。所以要怎么实现呢,那我们可以参考字符串拷贝,知道源内存首地址,知道内存空间大小,知道目标内存地址就可以连续地拷贝过去了。参照下列代码:

class A
{
public:
A()
{
arrayA = new int [size];//内存分配
for( size_t i = 0;i<size;i++)
{
arrayA[i] = i;
}
~A()
{
delete arrayA;
}
A(const A& object)//复制构造函数
{
char* source = &object; //得到目标地址,赋值给char指针目的是为了在指针运算时让系统按1个字节去递增
char* dest  = (char*)this;
/*获取目标地址,也就是本对象的地址,注意this指针是一个常量,且是一个非左值不能被赋值和修改,只能读取,所以要修改本对象的内容,只能通过获取本对象的地址,并将内容拷贝到本对象的地址中*/

for(size_t i = 0; i<sizeof(A);i++)
*(dest+i) = *(source+i);//内存拷贝,完成从源对象到目标对象的内存复制。
}
private:
const size_t size= 40;
int *arrayA;

}


上面的版本为了看清楚明白其中的原理再简化的版本

A(const A &object)
{
memcpy(this, &object,sizeof(A)); //呵呵就是这么简单
}


再扯一波,刚刚说到const指针this, const指针通常指的是指针本身不能被修改,但是其指向的内容可以被修改,this就是这种类型。还有一种是指向const内容的指针,这种这种指针本身可以被修改,但是其指向的内容不可以被修改。

具体的声明如下例如:

第一种:

const int *p = new int(10);//const在指针的左边,声明一个指针指向const int。
*p = 20;//错误,const内容不能被修改
p++//正确,指针不是const


第二种:

int * const p = new int(10);//const在指针的右边,声明一个const指针指向int。
*p = 20;//正确,内容不是const
p++//错误,指针是const
const int* const p;//内容和指针都是const都不能被修改


对于第一种如果我们要修改const内容该怎么办,那就是用const_cast<>(data)来去掉const属性

const int *p = new int(10);//const在指针的左边,声明一个指针指向const int。
*p = 20;//错误,const内容不能被修改
int *unconst_p = const_cast<int*>(p);
*unconst_p = 20;//去掉const属性之后正确
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  c语言