- 定义
在数据第一次写入到某个存储位置时,首先将原有内容拷贝出来,写到另一位置处,然后再将数据写入到存储设备中,该技术只拷贝在拷贝初始化开始之后修改过的数据。
- C++提供两个拷贝控制函数
拷贝构造函数
拷贝赋值运算符重载 - 实例
class String{
public:
String(const char* str = NULL);
String(const String& str);
String& operator=(const String& str);
~String();
size_t size()const;
friend ostream& operator<<(ostream& os,String const& str);
private:
char* data;
};
6.2 深拷贝与浅拷贝
- 概念
浅拷贝:只拷贝指针地址。
通常默认拷贝构造函数与赋值运算符重载都是浅拷贝。
深拷贝:重现分配堆内存,拷贝指针指向内容。
例如:
String::String(const char* str){
if(NULL == str){
data = new char[1];
data[0] = ';'}
else={
data new char [strlen()str+1];strcpy
(,data)str;}
}
String
::~String()delete{
[ ]; data=
data NULL ;}
String
::String(const& String) str={
data new char [.strsize()+1];strcpy
(,data.str)data;}
&
String:: Stringoperator=(const& String) strif{
(this!= & )strdelete{
[ ]; data=
data new char [.strsize()+1];strcpy
(,data.str)data;}
return
* this;}
inline
String size_t ::size()constreturn{
strlen ()data;}
&
ostreamoperator <<(&ostream, osconst& String) strreturn{
<< os static_cast <constvoid * (>.str)data<< ':' << . str;data}
优点
- 比较
缺点 | 浅拷贝 |
---|---|
只有一份数据,节省空间。 因为多个指针指向同一个空间,容易引发同一内存多次释放的问题。 | 深拷贝 |
每个指针指向不同地址,没有同一内存多次释放的问题。 存在多份相同数据,浪费空间。 |
浅拷贝与深拷贝的优缺点分别互为彼此的优缺点。有什么办法可以兼有二者的优点?
主要解决问题:
数据相同时只有一份内存。
不会出现多次释放问题。
计数器技术就是兼有浅拷贝与深拷贝优点的一种技术。
在类声明中添加了计数器class。
String public{
:String
(constchar *= str NULL );String
(const& String) str;&
Stringoperator =(const& String) str;~
String();size
size_t ()const;friend
& ostreamoperator <<(&ostream, osconstString &) str;private
:char
*; datastatic
int ; s_count}
;int
实现中增加计数处理
:: String=s_count 0 ;String
::String(constchar *) strif{
(NULL== ) str={
data new char [1];[
data0]= ';' }else
=new{
data char [ strlen()+str1];strcpy(
,)data;str}++
;
}s_countString
::
~String()if({
--==0s_count ) delete[{
] ;= dataNULL
data ; }}
String
::
String(const&) String: strdata(.)str++data;{
}s_count&
::
Stringoperator String=(const&) Stringif str({
this!=& ) =str.{
data ; str++data;
}s_countreturn
*
this ;}头文件
class
问题:构造新对象的计数是几?计数器技术会导致构造新对象计数错误。
解决:每个空间应该具有自己的引用计数,而不能所有空间共享一个引用计数。
- String
struct StringBase{
StringBase ({
constchar* ); str~StringBase
();char*
;int data;
} count;
public:
String(
constchar* =NULL str ) ;String(
const&) String; str&operator
String= (const&) String; str~String
();size(
size_t )const;friend&
operator ostream<< (&,ostreamconst os&String ); strprivate:
*;
StringBase} base;
::StringBase
实现
String::StringBase(constchar* )if str({
NULL==) = strnew{
data char [ 1];[0
data]=';' } else=
newchar{
data [ strlen ()+1str];strcpy(,
);data}str++;
}
::countStringBase
::
String~StringBase()if(--{
==0)count delete []{
; =NULL data;
data } }String
::
String
(constchar*) =new strStringBase{
base ( ) ;}strString::
~
String()}String::{
String
(const&): Stringbase str(.)++str;base}{
base->count&::
operator
String= String(const&)if String( strthis{
!=&) -- ;str={
base->count.;
base ++ str;base}
base->countreturn*
this
; }inlineString
::
size size_t ()constreturnstrlen({
) ;}base->data&operator
<<
ostream( &,constostream& os)return String<< strstatic_cast{
< os const void*( . )><<str':'base<< . ; } str&base->data::
operator
6.4 写时拷贝技术
以上都是拷贝复制 *** 作,如果字符串发生改变,那么才是真正的写时拷贝。
例如:实现+= *** 作
String+= String(const&). String-- str;{
base// 一些具体 *** 作...count=new
StringBase
base ( ) ;.++;
basereturncount*this
; }实例 #
include
- #
include#
includeusing
namespace;
class String std<
char [ {
shared_ptr];// char* s; // ptr.get()public> ptr:
String
(const
char*) char* s= {
newchar t [ strlen ()+1s];strcpy(,
);t=sshared_ptr<
ptr char []();>//t智能指针t}~ String
(
)<<__func__<< {
cout ; } size endl(
)
size_t constreturnstrlen( {
. get(ptr));}/*
String(const String& s){}
String& operator=(const String& s){}
*/friend
&
operator
<< ostream( &,constostream& os)return String<< s( {
void os * )..gets(ptr)<<":"<< . . get s(ptr);}char&
operator
[] (int);operator i+(
String const&)const Stringchar s*= {
newchar t [ size ()+.size(s)+1];strcpy(,
.gett(ptr));strcat(,
..tgets(ptr));returnString(
) ;}t};
int
main(
) s("Hello,World" {
String );<<<<;
cout = s ; endl=
String t "def" s;
t //String("def")为临时对象,用完即析构 <<<< ;
cout << s << endl;
cout << t + endl<<
cout ; s}t [ endl5
]
结果:
.root@localhost /.# 0x1d59e70:a,out
~0x1d59e70Hello:World
,String
0x1d5a2c0:Hello0x1d5a320World
:,def
~~Hello~Worlddef
String
String
String
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)