版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/LHshooter/article/details/83716552
引入
c++的堆和栈
class Person{
public:
Person(){ cout<<"new Person"<<endl; }
~Person(){ cout<<"~ Person"<<endl; }
};
int main(){
Person m;
Person* tt = new Person();
return 0;
}
程序运行结果:
new person
new person
~Person
注意到,析构函数只调用了一次,即m在main函数运行完作为栈变量被释放
Person m; 会存放在栈里面,
而Person* tt = new Person();存放在堆里面(需要自己delete释放堆空间)
那么如果都是存放在栈里面是不是就可以自己析构,就可以自回收
因此我们可以引入一个类作为中间类
c++中间类
class Person{
public:
Person(){ cout<<"new Person"<<endl; }
~Person(){ cout<<"~ Person"<<endl; }
void print(){ cout<<"...out Person..."<<endl; }
};
class sp{
private:
Person *p;
public:
sp(){ cout<<"new sp"<<endl; }
~sp(){ cout<<"~ sp"<<endl; if(p) {cout<<p<<endl; delete(p);} }
sp(Person *per){ p=per; cout<<"new sp Person*per"<<endl; }
sp(const sp &pers){ p=pers.p; cout<<"new sp"<<endl; }
Person* operator->(){ return p; } //定义->的操作功能
Person& operator*(){ return *p; }
};
void test(){ sp other = new Person(); }
int main(){
test();
return 0;
}
程序运行结果:
new Person
new sp
~sp
~ Person
注意到~sp(){ if(p) delete(p); } 如果会delete,但是第二次if(p),new Person 仍然不会析构
sp other = new Person(); 实际相当于两步 Person *tmp = new Person(); sp other = *tmp–>即调用 sp()的构造函数
如果代码稍微修改下
void test(sp &temp){ sp tt = temp; tt->print() }
int main(){
sp other = new Person();
test(other);
return 0;
}
运行会奔溃:
new Person
new sp Person *per
new sp sp &pers
~sp
0x1d9a010
~ Person
0
~sp
0x1d9a010
~ Person
*** glibc detected *** ./pointer: double free or corruption (fasttop): 0x0000000001d9a010 ***
错误1: 创建了两个sp ,会执行两次析构 ~sp 而 if(p) delete(p); 这里判断会调用两次。sp other = new Person(); test(other);。
现在我们来分析下上面的代码
改进-增加引用计数
sp other = new Person();
test(other);
上面两行代码的问题在于,sp有一个引用sp tt,调用结束,tt是保存在栈中,调用结束tt将调用sp的析构函数。当回调主函数other又是一个栈中的对象,则又会调用一次析构函数,而if(p)的判断这里似乎无效。
在sp中,Person 是通过sp来调用,Person的析构也由sp掌握,因此只有当确认Person不再被任何sp对象(引用)调用时,才delete Person。
每new sp 且给 Person *p赋值处增加引用计数,在析构中引用递减
class Refbase{
private:
int count;
public:
Refbase():count(0){}
void incStrong(){ count++; }
void decStrong(){ count--; }
int getStrongCount(){ return count; }
};
class Person:public Refbase{
public:
Person(){
cout<<"new Person"<<endl;
}
Person(const Person &t){
cout<<"new Person t"<<endl;
}
Person(Person *tt){
cout<<"new Person *tt"<<endl;
}
~Person(){
cout<<"~ Person"<<endl;
}
void print(){ cout<<"cout person"<<endl; }
};
class sp{
private:
Person *p;
public:
sp():p(0){ cout<<"new sp"<<endl; }
~sp(){
cout<<"~sp"<<endl;
if(p){
p->decStrong();
if(p->getStrongCount() == 0){
delete(p);
p = NULL;
cout<<p<<endl;
}
}
}
sp(Person *per){
p=per;
p->incStrong();
cout<<"new sp Person *per"<<endl; }
sp(const sp &pers){
p=pers.p;
p->incStrong();
cout<<"new sp sp &pers"<<endl; }
Person* operator->(){ return p; } //定义->的操作功能
Person& operator*(){ return *p; }
};
void test(sp &tmp){
sp other = tmp;
other->print();
}
int main(){
sp oth = new Person();
test(oth);
cout<<"this is test"<<endl;
return 0;
}
再次改进–使用模板template
使用template<typename T>
类模板来操作,但是要注意,必须要每个使用的函数钱添加类模板定义
using namespace std;
class Refbase{
private:
int count;
public:
Refbase():count(0){}
void incStrong(){ count++; }
void decStrong(){ count--; }
int getStrongCount(){ return count; }
};
class Person:public Refbase{
public:
Person(){
cout<<"new Person"<<endl;
}
Person(const Person &t){
cout<<"new Person t"<<endl;
}
Person(Person *tt){
cout<<"new Person *tt"<<endl;
}
~Person(){
cout<<"~ Person"<<endl;
}
void print(){ cout<<"cout person"<<endl; }
};
template<typename T>
class sp{
private:
T *p;
int vale;
public:
sp():p(0),vale(0){ cout<<"new sp"<<endl; }
~sp(){
cout<<"~sp"<<endl;
if(p){
p->decStrong();
if(p->getStrongCount() == 0){
delete(p);
p = NULL;
}
}
}
sp(T *per){
vale = 1;
p=per;
p->incStrong();
cout<<"new sp T *per"<<endl; }
sp(const sp &pers){
p=pers.p;
vale = 2;
p->incStrong();
cout<<"new sp sp &pers"<<endl; }
T* operator->(){ return p; } //定义->的操作功能
T& operator*(){ return *p; }
};
template<typename T>
void test(sp<T> &tmp){
sp<T> other = tmp;
}
int main(){
sp<Person> oth = new Person();
test(oth);
return 0;
}
再次改进–引用计数增加原子操作
ctemplate<typename T>
class Refbase{
private:
mutable volatile int32_t count;
public:
Refbase():count(0){}
void incStrong(){
__sync_fetch_and_add(&count, 1);
//count++;
}
void decStrong(){
//count--;
if (__sync_fetch_and_sub(&count, 1) == 1) {
delete static_cast<const T*>(this); //注意这里实现了delete操作
}
}
int getStrongCount(){ return count; }
};