09. 友元,引用计数
1.友元
1.1可以访问所有成员(公有,私有)
2.1友元不是类的成员,也不受它所在区域访问控制级别的约束
2.2普通函数,类的成员函数,整个类都可以声明为友元
2.3友元破坏了封装性,不到万不得已不要用
2.4运算符重载时适合用友元
class HasPtr;//前向声明
class Test {
public:
void Test1();//不能在此处写创建HasPtr对象的函数实现,因为HasPtr尚未给出定义,编译器不清楚它的成员和size。
void Test2();
private:
HasPtr *pointer;//指针或引用可以,即使HasPtr尚未给出定义
};
class HasPtr {
friend void Test::Test1();//成员函数作为友元,Test类中其他未声明为友元的函数不能访问HasPtr的私有成员
//friend Test;//类作为友元,Test类中都能访问HasPtr的私有成员
friend int main();//声明main函数是友元
friend void Foo() {//类内部定义了友元,是全局函数,使用前需要再声明
HasPtr foo;
foo.count = 99;
}
public:
HasPtr(int *p = nullptr, int n = 0) :ptr(p), count(n) {}
private:
int *ptr;
int count;
};
void Test::Test1() {//此处有完整的HasPtr的定义了,可访问
HasPtr ptr;
ptr.count = 0;
}
void Foo();//使用前需要再声明
int main() {
HasPtr ptr;
ptr.count = 124;//可以直接访问私有成员
Foo();//使用全局函数
return 0;
}
2.引用计数
浅拷贝:节省资源,内存利用率高,没管理好会出现重复释放资源的问题。
深拷贝:消耗资源,内存利用率低,不会重复释放。
写时复制:想要修改某对象时,分配一块新内存,把该对象复制过来,在新内存中修改。
如果计数器作为成员直接保存在类中,想修改计数器的值,需要修改每个类中的成员,不合适。
如果计数器作为静态成员,想修改计数器的值,直接静态成员即可,合适。但写时复制时需要一个新的静态成员保存新的计数器值,那么实现定义几个静态成员呢?这一点无法确定,也不合适。
如果计数器保存在堆里,类中保存指向计数器的指针,想修改计数器的值,可通过指针修改,合适。写时复制时需要申请一块新的堆内存保存数据和新计数器的值,并递减原计数器值,这一点比静态成员灵活,也合适。

浙公网安备 33010602011771号