指针调用成员函数本文作者:黄邦勇帅
本文是学习C++的附加内容,主要介绍了C++中的string类的各种成员函数,及成员函数的功能与作用,是作为学习C++的参考使用的。
本文内容完全属于个人见解与参考文现的作者无关,其中难免有误解之处,望指出更正。
声明:禁止抄袭本文,若需要转载本文请注明转载的网址,或者注明转载自“黄邦勇帅”。
主要参考文献:
1、C++.Primer.Plus.第五版.中文版[美]Stephen Prata著孙建春韦强译人民邮电出版社2005年5月
2、C++.Primer.Plus.第四版.中文版Stanley B.Lippman、Barbara E.Moo著李师贤等译人民邮电出版社2006年3月
3、C++.Primer.Plus.第三版.中文版Stanley B.Lippman等著潘爱民张丽译中国电力出版社2002年5月
4、C++入门经典第三版[美]Ivor Horton著李予敏译清华大学出版社2006年1月
5、C++参考大全第四版[美]Herbert Schidt著周志荣朱德芳于秀山等译电子工业出版社2003年9月
6、21天学通第四版C++ [美]Jesse Liberty著康博创作室译人民邮电出版社2002年3月
第20章string类
1、string类用于处理字符串,要使用string类需要包含string头文件。
2、注意string是一个类,它具有类的特性,也就是说string类有构造函数,有重载的操作符,有成员函数。string对象
可以自动调整大小,但有一些限制,string对象有个最大允许的长度,该长度由string类的静态常量string::nops设定,通常是最大的unsigned int值,在vc++中被设为-1。
3、string类是模板类basic_string类的char具体化版本,basic_string类的原型为:template<class charT, class
traits=char_traits<charT>, class Allocator=allocator<charT> > class basic_string{….}; 对于string类具有预定义的具体化版本typedef basic_string<char> string;也就是说string是basic_string模板类的char具体化版本的别名。
4、string类的size_type类型,size_type是string中的配套类型,一般被定义为unsigned类型。可以使用限定名的方法
来使用size_type类型,比如string::size_type a;
5、string类的构造函数:string类有6种形式的构造函数,string类是basic_string类的特化版本,因此他的构造函数就
是basic_string模板类的char特化版本的构造函数,在这里我们省略掉其他复杂的形式,得到以下的string构造函数版本,具体的basic_string模板类的构造函数这里不讨论。
a、string(const char *s);将string对象初始化为s指向的传统C字符串(即以空字符结束的字符串)。比如string
one(“hyong”);将string对象one用字符串hyong来初始化。这就意味着可以把char类型的数组转换为string对象,比如string a; char b[]=”ldki”; 则a=b; string c=b;都是正确的。但不能将string对象的字符串转换为char类型的数组。
b、string(size_type n,char c);创建一个包含n个元素的对象,其中每个元素都被初始化为字符c。比如string two(10, ‘c’);
将string对象two初始化包含为十个字符c。这意味着不可以用单个字符来初始化string类型的对象,比如string a=’s’;
将发生错误。
c、string();创建一个默认的string对象,长度为0。比如string three;即表示创建一个长度为0的字符串对象three。
d、string(const string &str, size_type pos=0,size_type n=npos);将string对象初始化为string对象的字符串从pos开始到
结尾的字符,或从pos开始的n个字符。
e、string(const char *s, size_type n);将string对象初始化为s指向的传统C字符串中的前n个字符,即使超出了字符串
的范围,操作仍会进行。比如char all[]=”hyong”; string five(all, 5);表示用字符数组all的前5个字符来初始化string 对象five。注意即使复制的长度超出了数组的长度,操作仍将进行,也就是说如果把5改为10的话,将导致5个无用的字符被复制到对象中。
f、tempalte<class Iter>string(Iter begin, Iter end);将string对象初始化为[begin, end]间的字符,其中begin和end就像
指针,用于指定位置,范围包括begin在内,但不包括end,注意不包括end。还要注意begin和end被看着指针,也就是说char all[ ]=”hyongilfmm”; string seven(all+2, all+4)将使用从第all+2的字符o开始到第all+3的字符n初始化对象seven,最后seven为”on”。因为字符串从0开始计数,所以这里从第3个字符开始。而all+3指的是第4个字符,注意all+4指的是第5个字符,这里不以第5个字符g结束,因为该构造函数不包括end在内。还要注意,对begin和end被看着指针指向某一位置,也就是说string a=”hyong”;string b(a+3, a+5);是错误的,因为a是string类对象,不是指针,所以a+3没有意义,所以这里应这样string b(&a[3], &a[5])这里a[3]是一个char值,&a[3]是一个地址。
6、注意,不能用单个字符来初始化string对象,比如string a=’d’;将是错误的,但是string a(1,’d’)是正确的,这里将把’d’
初始化为”d”。
7、string对象只能接收以空字符结尾的字符串,比如语句char b[ ]={‘a’, ‘b’, ‘c’}; string a=b;将是错误的。
8、string对象的输入:可以使用cin和getline函数对string对象进行输入,注意不能使用get函数,getline()函数读取字
符到string对象中直到达到以下条件时停止:1、到达文件尾,这种情况下输入流的eofbit将被设置。2、遇到分界符。
3、读取的字符达到string对象的最大允许值,这时将设置failbit。
9、string类的输入函数getline():该函数的原型为:template<class charT, class traits, class Allocator> basic_istream<charT,
traits>& getline(basic_istream<charT, traits>& is, basic_string<charT, traits, Allocator>& str, charT delim);该函数表示,对于string类,简省的getline函数为string & getline(istream& is, string& str, char delim);表示把输入流is中的字符读入到字符串str中,直到遇到分界符delim,到达文件尾或到达字符串的最大长度,分界符delim将被读取并删除。第二个版本的getline()函数没有最后的分界符参数。注意这个版本的getline函数与前面介绍的不一样。调用这个版本的getline函数是直接调用,比如string a; getline(cin, a, ‘z’);把输入流cin中的字符读入到string对象a中,直到遇到分界符z为止。而这些调用都是错误的,a.getline(cin,a,’z’);line(cin, a, ‘z’);另一点就是第一个参数必须要是一个输入流的对象,在这里输入流是标准输入流cin。还要注意的是这个版本的getline函数只能适用于string对象,而string对象也只能使用这个版本的getline函数,比如这些使用方法都是错误的,char a[3]; getline(cin, a);错误字符数组a无法转换为string对象,string a; line(a, 4);试图从输入流中读取4个字符到stri
ng对象a中,该函数的原型接受的是char类型的数组,所以也存在无法将string对象a转换为char类型的错误,string对象只能使用现在介绍的这个getline()版本。
10、string类重载的操作符如下:string重载了关系运算符,赋值运算符,[]运算符,+加运算符。对于关系运算符,数字
小于大写字符,大写字符小于小写字符。重载的[]运算符使得string对象可以像使用数组一样。重载的+运算符可以让两个string对象相加,注意对于+运算符操作数的两边必须有一个是string类型的对象,不能将两个字符串直接相加,比如string b=”iwf”; string a=”hyon”+”onfg”+b;就是错误的,但string a=”hyon”+(”onfg”+b);就是正确的。
11、string类的成员函数:
11.1、find()方法:find方法有几个重载版本,分别如下,在这里介绍的find函数原型是basic_string模板类的char特化
版本string的原型,也就是说对basic_string模板类中的find()函数作了简化。
a、size_type find(const string &str, size_type pos=0) const从位置pos开始查子字符串str,如果到,则反回该子
字符串首次出现时其首字符的索引,否则反回string::npos,由前所述npos是类string中的静态常量,表示string 对象能存储的最大长度。比如string a=”hyongilsdfmgkd”; string b=”ong”; int c; c=a.find(b,1)表示从string对象a的第1个位置开始即字符y开始,注意这符串以0开始,查string对象b中的字符串”ong”如果到则反回起始位置,如果没到则反回string::pos。
b、size_type find(const char *s, size_type pos=0) const 从位置pos开始查子字符串s,如果到,则反回该子字符
串首次出现时其首字符的索引,否则反回string::npos,这个版本的find函数和第一个版本一样,只不过第一个参数是char类型的字符数组,而不是string对象。
c、size_type find(const char *s, size_type pos, size_type n)从string类型的字符串的pos位置开始,查char类型的
数组s的前n个字符组成的子字符串,如果到,则反回该子字符串首次出现时其首字符的索引,否则反回string::npos。注意这个版本的find函数只适用于char类型的数组,而不适用于string对象,比如string a=”hyongsldjfoidfj”; string b=”ong”; char c[]=”ong”;int d;则d=a.find(c,1,3)则表示从string对象的第1个位置开始查由字符数组的前3个字符组成的字符串,如果到则反回起始位置,如果没到则反回string::pos。但是语句d=a.find(b,1,3)将发生错误,因为string对象b不是字符数组,所以发生错误。还要
注意的是函数的第二个参数pos 指的是调用该函数的string对象的位置,比如string a=”edklkkk”; char b[]=”jidkik”; int c=a.fing(b,2,2);这里并不是从string类型a的字符串的开始位置查由char类型的数组b从位置2开始的两个字符”dk”,而是指从string类型的对象a的第2个位置k开始查由char类型的数组b的前两个字符”ji”,所以最后未到这两个字符而反回-1。
d、size_type find(char ch, size_type pos=0) const 从位置pos开始查字符ch,如果到,则反回该字符首次出现时
的位置,否则反回string::npos
11.2、at()成员函数:at()函数的功能与[ ]操作符相似,都是用于访问string对象中的单一的字符,区别在于at()函数会
执行边界检查,而[ ]操作符不会。其原型为reference at(size_type n);const_reference at(size_type n) const;第一个函数用于检索或更改字符串的值,第二个函数用于const对象,只能用于检索其值。调用方法为:string a=”hyong”;
cout<<a.at(1);输出下标为1的单个字符y。
11.3、substr()成员函数:该函数用于反回原始字符串的子字符串。其原型为basic_string substr(size_ty
pe pos=0, size_type
n=npos) const;表示反回由pos开始的n个字符,其默认参数为反回整个字符串。调用方法为:string a=”hyongkdlsi”;
cout<<a.substr(2, 5);表示反回从下标2开始的5个字符ongkd,如果指定的字符数超过了string对象的结尾,则substr()函数只反回从指定位置到string对象尾的字符。如果指定的起始位置超出了string对象的结尾,则抛出一个异常。
对于以下的成员函数要注意的是string是basci_string模板类的char特化版本,也就是说如果是string对象则类型charT 应被替换为char,basic_string应被替换为string。
11.4、compare()成员函数:该函数用于比较两个字符串的大小,其功能与使用关系运算符进行比较相似。其比较规则
为如果第一个字符串大于第二个字符串则反回一个大于0的值,如果第一个字符串小于第二个字符串的值则反回一个小于0的值,如果两个字符串相等则反回0,如果第一个字符串比第二个字符串短则与第二个字符串的前部分相同,则反回一个小于0的值。注意compare()函数是string类的成员函数,所以使用compare函数时应使用string类的对象来调用。compare()函数的五个原型为:
a、int compare(const basic_string &str) const;比如string a=”hyongldfki”; string b=”hyongilfdke”; int c=apare(b);表
示把string对象a与对象b进行比较,比较的结果是a小于b函数反回一个小于0的值。
b、int compare(size_type pos1, size_type n1, const basic_string &str) const;将第一个字符串从pos1位置开始的n1个字
符与第二个字符串进行比较。比如string a=”ahyongldlkfi”; b=”hyongldiekf”; int c=apare(1,5,b);将string对象a 从第标号为1开始的5个字符与第二个字符串相比,结果对象a小于对象b,反回一个小于0的值。
c、int compare(size_type pos1,size_type n1, const basic_string &str, size_type pos2, size_type n2) const;将第一个字符串
从pos1开始的n1的字符,与第二个字符串从pos2开始的n2个字符进行比较。比如string a=”ahyongidlfjm”;
b=”adhyongldi”; int c=compare(1,5,b,2,5);将对象a从位置1开始的5个字符与对象b从位置2开始的5个字符进行比较,结果两个对象相等,反回值0。
d、int compare(const charT *s) const;这个版本与第1个版本相同,只不过该版本用于char类型的数组。
e、int compare(size_type pos1, size_type n1, const charT* s, size_type n2=npos) const;这个版本与第3个版本相同,只
不过这个版本用于char类型的数组。注意,这里的函数原型有4个参数,只适合于char类型的数组对象,对于string的对象就是错误的用法,比如string a=”hyong”; string b=”kdl”; int c=apare(1,2,b,2);就是错误的,这里试图将string对象a从位置1开始的2个字符与string对象b的前两个字符进行比较,这里就错在string对象b与compare的函数原型中的charT*类型不相符合。
f、对于compare()函数可以直接用字符串进行比较,比如  apare(“dfoei”);apare(1,2,”dkife”);
apare(1,2,”dosdife”,3); apare(1,2,”dfsl”,1,2);都是正确的。
11.5、append()成员函数:该函数用于将一个字符串追加到另一个字符串的后面,其使用功效与使用+=相似。append()
函数有以下几个原型:
a、basic_string &append(const basic_string& str);将str的内容追加到原字符串的末尾。
b、basic_string& append(const basic_string& str, size_type pos, size_type n);
c、template<class InputIterator> basic_string& append(InputIterator first, IputIterator last);
d、basic_string& append(const charT* s);
e、basic_string& append(const charT* s, size_type n);
f、basic_string& append(size_type n, charT c);
11.6、assign()成员函数:该函数用于将一个字符串赋给另一个字符串,功能与使用=赋值运算符相似。assign()函数有
以下几个原型:
a、basic_string& assign(const basic_string& str); 用字符串str替换原有字符串的内容,比如string a=”hyong”; string
b=”hemi”; a.assign(b);表示用string类型b替换掉a的内容,最后a为”hemi”。
b、basic_string& assign(const basic_string& str, size_type pos, size_type n);使用str中位置从pos开始
的n个字符替
换原有内容,比如string a=”hkel”; string b=”hyong”; a.assign(b, 2,3);使用从b的位置2开始的3个字符”ong”替换原有的内容,最后a的内容为”ong”。
c、basic_string& assign(const charT* s, size_type n);使用char类型的数组的前n个字符替换原有的内容,比如string
a=”kdi”; char b[ ]=”hyongk”; a.assign(b, 3);表示用数组b的前3个字符”hyo”替换掉a的内容,最后a为”hyo”,这里要注意,该函数的第一个参数charT*只适用于char类型的数组,如果传递给第一个的参数是string类型的对象则会出错。
d、basic_string& assign(const charT* s);使用char类型的以空字符结尾的字符串替换原有的内容。
e、basic_string& assign(size_type n, charT c);使用n个字符c替换原有的内容。
f、template<class InputIterator> basic_string& assign(InputIterator first, InputIterator last);
11.7、insert()成员函数:该函数可以将一个字符串插入到一个string对象中,该函数与append()类似,不过insert()接受
另一个指定插入位置的参数,该参数可以是位置也可以是迭代器。数据被插入到插入点的前面。insert()函数有以下几个原型:
a、basic_string& insert(size_type pos1, const basic_string& str);将string类型的字符串插入到pos1的位置的前面,
比如string a=”hyongdk”; string b=”u”; a.insert(2,b);将字符串b中的字符插入到a中的第2个位置o的前面,最后a为”hyaongdk”。
b、basic_string& insert(size_type pos1,const basic_string& str, size_type pos2, size_type n);将string类型的字符串str
从位置pos2开始的n个字符插入到string类型的对象位置在pos1前面的位置中。比如string a=”hyong”; string b=”iklfmgie”; a.insert(2,b,3,2);表示将string类型的字符串b从位置3开始的2个字符”fm”插入到string类型的字符串a在位置2的前面最后a成为”hyfmong”。注意:该语句中basic_string& str也可以用于char类型的数组,因为char类型的数组可以转换为sring对象。
c、basic_string& insert(size_type pos, const charT* s, size_type n);表示将由char类型的字符数组的前n个字符插入
到string类型的对象中在位置pos的前面。比如string a=”hyong”; char b[ ]=”ikldke”; a.insert(2, b, 3);表示将字符数组的前3个字符”ikl”插入到string对象的位置2的前面,最后a成为”hyiklong”。
d、basic_string& insert(size_type pos, const charT* s);表示将整个char类型的数组插入到string对象中的位置在pos
的前面。
e、basic_string& insert(size_type pos, size_type n, charT c);插入n个字符c到string类型对象位置在pos的前面。
比如string a=”hyong”; a.insert(2,4,’c’);插入4个字符c到a的位置2的前面,最后a成为”hyaaaaong”。
f、iterator insert(iterator p, charT c=charT());
g、void insert(iterator p, size_type n, charT c);
h、template<class InputIterator>void insert(iterator p, InputIterator first, InputIterator last);
11.8、erase()成员函数:该函数从字符串中删除字符。erase()函数有以下几个原型。
a、basic_string& erase(size_type pos=0, size_type n=npos);从位置pos开始删除n个字符或删除到字符串尾。
b、iterator erase(iterator position);删除迭代器位置引用的字符,并反回指向下一个元素的迭代器,如果后面没有其
他元素则反回end();
c、iterator earse(iterator first, iterator last);删除区间[first, last)中的字符,即删除从包括first开始的位置到不包括
last的位置之间的字符。它反回一个迭代器,该迭代器指向最后一个被删除的元素后面的一个元素。
11.9、replace()成员函数:该函数用于替换字符串的内容。有如下几个原型:
a、basic_string& replace(size_type pos1, size_type n1, const basic_string& str);将string类型的对象从位置pos1开始
的n1个字符替换为string类型的对象str,比如string a=”hyongkdik”; string b=”ffff”; a.replace(5,4,b);把a从位置5开始的4个字符”kdik”替换为ffff,最后a成为”hyongffff”。
b、basic_string& replace(size_type pos1, size_type n1, const basic_string& str, size_type pos2, size_type n2);表示把
string对象从pos1开始的n1个字符替换为字符串str从pos2开始的n2个字符。比如string a=”hyongdkk”; string b=”hemi”; a.replace(5,3,b,2,2);将a从位置5开始的3个字符”dkk”替换为b从位置2开始的2个字符”mi”,最后a 为”hyongmi”。
c、basic_string& replace(size_type pos,size_type n1,const charT* s, size_type n2);表示把string对象从位置pos开始的
n1个字符替换为char数组类型的前n2个字符。
d、basic_string& replace(size_type pos, size_type n1, const charT* s);表示把string对象从位置pos开始的n1个字符
替换为char数组类型的字符。
e、basic_string& replace(size_type pos, size_type n1, size_type n2, charT c);表示把string对象从位置pos开始的n1
个字符替换为n2个char类型的字符c。比如string a=”hyongldkfi”; a.replace(5,5,3,’s’);表示把a从位置5开始的5个字符”ldkfi”替换为3个字符s,最后a为”hyongsss”。
f、basic_string& replace(iterator i1, iterator i2, const basic_string& str);
g、basic_string& replace(iterator i1, iterator i2, const charT* s, size_type n);
h、basic_string& replace(iterator i1, iterator i2, const charT* s);
i、basic_string& replace(iterator i1, iterator i2, size_type n, charT c);
j、template<class InputIterator> basic_string& replace(iterator i1, iterator i2, InputIterator j1, InputIterator j2); 11.10、copy()成员函数:该函数用于将string对象或其中一部分复制到指定的字符串数组中,其原型为:size_type
copy(charT* s, size_type n, size_type pos=0) const;将string对象中从位置pos开始的地方复制n个字符到指定的数组s中。函数反回复制的字符数,该函数不追加空值字符,且不进行数组的长度的检查。
11.11、swap()函数:该函数交换两个string对象的内容,其原型为:void swap(basic_string<charT, traits, Allocator>&);
11.12、length(), size()成员函数:这两个成员函数功能相同,使用不带参数的length,size函数能反回string对象中的实
际元素数。
11.13、capacity()成员函数:该成员函数反回string对象的容量,也就是说一个string对象最多能存储多少个字符,这
个数字可能大于size(),length()的数目,capacity()-size()表示string对象还能存储多少个字符。
12、C风格字符串:c风格字符串是以空字符null结束的字符数组。比如char a[ ]={‘a’,’b’}就不是一个C风格字符串,因
为该数组不是以空字符结束的字符数组。而char b[ ]={‘a’,’b’,’\0’}则是C风格的字符串。再如char a[3]=”abc”;将发生数组溢出的错误,因为字符串”abc”有4个字符,最后还有一个空字符’\0’,反以数组a应该声明为有4个成员的数组才对,即char a[4]=”abc”。
13、C风格字符串的标准库函数,在使用C风格字符串的库函数时须要包含头文件#include <cstring>,传递给C风格字
符串的库函数的参数都必须是指针或者地址,调用这些函数时可以直接调用,具体内容如下:
a、strlen(s);反回s的长度,不包括字符结束符null。注意该函数处理的对象一定是要以空字符null结束的字符数组,
比如char a[ ]={‘a’,’b’}; strlen(a);这时就会出错,因为当调用strlen函数时,系统将从实参a指向的地址开始搜索,直到遇到null结束符为止,strlen()反回这一段空间的长度,在该例中由于数组a没有null结束符,所以最后的结果是无法预料的。
使用以下的库函数时一定要确定数组s1的大小有足够的空间,还要注意最后的null结束符要占一个位置。
b、strcmp(s1,s2);比较字符串s1和s2,如果s1大于s2反回正数,如果s1小于s2反回负数,如果s1等于s2反回0。
c、strcat(s1,s2);将字符串s2连接到s1后,并反回s1。
d、strncat(s1,s2,n);将s2的前n个字符连接到s1后面,并反回s1。
e、strcpy(s1,s2);将s2复制给s1,并反回s1。
f、strncpy(s1,s2,n);将s2的前n个字符复制给s1,并反回s1。
14、智能指针auto_ptr类:
智能指针的作用:智能指针能够防止使用动态内存new分配时忘记使用delete释放指针所指向的对象的情况,还可以防止两个指针指向同一个对象时一个指针释放了该对象而另一个指针还认为该对象存在的情况。比如void f(){string *p=new string(“dk”); ….return;}在函数f结束时就忘记使用了delete语句来释放指针p所指向的对象。再比如void f(){string *p=new string(“dk”); string *p1; p1=p; delete p;cout<<*p1;}在函数f中,把动态指针p赋给指针p1,这时指针p和p1指向同一个对象,但语句delete p删除了他所指向的内容,而指针p1这时并不知道指针p指向的内容已经不存在了,这时指针p1指向了一个不存在的对象,所以语句cout<<*p1;将是错误的。智能指针就能防止以上两种错误的情况出现。
15、auto_ptr类是一个模板类,其原型为:template<class X> class auto_ptr{public: explicit auto_ptr(X* p=0)throw();……};
其使用方法为:auto_ptr< double> p1(new double);这里new double分配的内存空间反回的指针被传递给auto_ptr类构造函数的形参p,在这里就为p1动态分配了一个智能指针的存储空间,使用auto_ptr类声明的指针有和常规指针相似的特征,但可以不用使用delete语句来释放内存空间,auto_ptr类会执行这个操作。例如void f(){auto_ptr<string> p1(new string(“dk”));….return;}在函数结束时不再需要delete语句,auto_ptr类会自动执行这一操作。
16、使用auto_ptr类的注意事项:
a、使用auto_ptr类需要包含头文件memory,且不需再使用delete语句。
b、auto_ptr类的构造函数是显示的,即explicit类型,也就是说不存在从指针到auto_ptr对象的隐式转换,以下的使
用都将是错误的:double *p=new double(2); auto_ptr<double> pd=p; 错误,不存在隐式转换,不可以这样初始化auto_ptr对象;
17、使用计数器自已实现智能指针类的方法:该方法可以解决类中含有指针对象的情况。
a、首先应将该智能指针类中的计数器与类的对象相关联,计数器跟踪该类有多少个对象共享同一个指针,当计数器
为0时删除对象。比如将类hyong声明为智能指针类u_ptr的友元。
b、每次创建类的新对象时,初始化指针,并将计数器设为1。
c、当对象作为另一对象的副本而创建时,复制构造函数复制指针并增加与之相应的计数器的值。
d、对一个对象进行赋值时,赋值操作符减少左操作数所指对象的计数器的值(如果计数器为0,则删除对象),并增加
右操作数所指对象的计数器的值。
e、最后,调用析构函数时,析构函数减少计数器的值,如果计数器减至0,则删除基础对象。
具体例子如下
例:定义智能指针类:
class u_ptr{friend class hyong; //把要使用智能指针的类hyong声明为智能指针类的友元。
int *ip; size_t use; //声明一个计数器。
u_ptr(int *p):ip(p),use(1){} //定义带一个参数的构造函数,并将计数器初始化为1。
~u_ptr(){delete ip;}};//析构函数。
//带指针的类hyong的定义
class hyong{u_ptr *ptr; int val;
public:
hyong(int *p,int i):ptr(new u_ptr(p)),val(i){} //定义构造函数
hyong(const hyong& orig):ptr(orig.ptr),val(orig.val){++ptr->use} //复制构造函数,当复制一个对象时增加计数器的值。hyong& operator=(const hyong& rhs ) //重载赋值操作符
{++rhs.ptr->use; //将右操作数的计数器加1,该操作可以防止自身赋值。
if (--ptr->use= =0) delete ptr; //将左操作数的计数器减1,如果为0则释放该指针指向的对象。
ptr = rhs.ptr ; val=rhs.val; return *this;} //复制对象,并反回这个对象。
~hyong(){if (--ptr->use = =0) delete ptr;}};//调用析构函数,调用一次就将计数器减1,如果计数器为0就释放指针指向的对象。
作者:黄邦勇帅

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。