c++中有哪些拷贝方式

介绍

这期内容当中小编将会给大家带来有关c++中有哪些拷贝方式,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。

浅拷贝
浅拷贝就其他两种而言就相当的简单了,其编写的代码如下:

字符串:字符串(字符串常量,s)
,,:_str (s._str)
,,_size (s._size)
,,_capacity (s._capacity)
{}

字符串,字符串::操作符=(常量字符串,s)
{
,,如果(_str !=s._str)
,,{
,,,,删除[]_str;
,,,,_str=s._str;
,,,,_size=s._size;
,,,,_capacity=s._capacity;
,,}
,,返回*;
}

虽然这种方法非常简单,但这种方法存在很大的漏洞,这种方法拷贝构造以及赋值运算符的重载后的对象与被拷贝的对象指向同一块空间,如果使用其中一个对象对其中的值进行修改时会导致另一个对象中的值也会发生改变,所以一般情况下不会使用浅拷贝这种拷贝方式。

但当对象中的值不能进行改变是一个const常量时,对象只可进行读不能进行修改,使用浅拷贝可减少内存的开销,不会有问题。

深拷贝
通过了解浅拷贝,我们发现浅拷贝的问题在于没有新空间的开辟所导致不能对对象中的值进行改变。但我们大部分的对象中的值都会需要进行修改,所以深拷贝就是为了解决这问题而出现的。既然指向空间相同就不能随意更改对象中内容,那么深拷贝就先给需要拷贝的对象开辟空间,再将内容拷贝过去。深拷贝分为传统写法以及现代写法这两种方法,其编写的代码如下:

类字符串
{
公共:
,,字符串(const char * str=啊?;
,,字符串(const String&年代);
,,String&运算符=(const String&年代);
,,~字符串();私人:

,,char * _str;
}

//传统写法完成字符串深拷贝
//字符串::字符串(const char * str)
//,: _str(新char [strlen (str) + 1])
//{
//,拷贝字符串(_str str);
//}
//
//字符串::字符串(const String&)//必须用引用否则会无限的递归
//,: _str(新char [strlen (s._str) + 1])//开辟。_str大小的空间,+ 1是因为‘/0
//{
//,拷贝字符串(_str s._str);
//}
//
//String&字符串::操作符=(const String&s)
//{
//,如果(这!=,s)//判断是否相同
//, {
//,,,如果(_str)
//,,,,,删除[]_str;//_str不为空,则需要先释放空间
//,,,_str=new char [strlen (s._str) + 1];
//,,,拷贝字符串(_str s._str);
//,}
//,返回*;
//}
//
//字符串::~字符串()
//{
//,如果(零!=_str)
//, {
//,,,删除[]_str;
//,//}}

//现代写法完成字符串深拷贝字符串
::字符串(const char * str)
,,:_str(新char [strlen (str) + 1])
{
,,strcpy (_str, str);
}

字符串::字符串(const String&s)
{
,,字符串tmp (s._str);//用。_str定义一个tmp对象
,,交换(_str tmp._str);//将指针进行交换
}

String&字符串::操作符=(String s)//形参调用构造函数
{
,,交换(_str s._str);
,,返回*;
}

字符串::~字符串()
{
,,如果(零!=_str)
,,{
,,,,删除[]_str;
,,}
}

相比较两种方法而言,更推荐现代写法,原因如下:

现代写法代码量相对而言较少,效率更高
现代写法的赋值运算符重载中调用了拷贝构造,拷贝构造中调用了构造函数,故现代写法中的复用性更强,更易于管理
传统写法中的赋值运算符重载会先释放原先开辟的空间,这样如果下面重新开辟空间失败不能拷贝时,那么原有数据不会被保留

深拷贝虽然会再次开辟空间增加内存的占用,但这样可以解决浅拷贝不能做到的问题。


写时拷贝
其实通过上面两种拷贝方式就可以解决很多问题,但浅拷贝不能修改,深拷贝如果不修改又占有了更多空间,因此写时拷贝就出现了,其实写时拷贝就是将上面两种方法的优点进行结合,通过引入一个引用计数来解决这些问题。
写时拷贝较上面方法更为复杂,所以在这里先进行说明:写时拷贝需要一个引用计数,因此要增加一个存放一个引用计数的位置,我们将这个位置放在_str前面的四个字节,每当拷贝一次就将引用计数+ +一次,进行修改时先判断一下引用计数是否为1,若为1则直接进行修改,否则先重新开辟一块空间,将原有引用计数,再进行修改。

下面简单编写一下其代码:

类字符串
{
公共:
,,字符串(char * str=啊?
,,,,:_str(新char ((strlen (str) + 5)))//多开辟4个字节来存放引用计数
,,{
,,,,* ((int *) _str)=1;
,,,,_str +=4;//str中内容在引用计数后

c++中有哪些拷贝方式