智能指针
◼ 传统指针存在的问题
需要手动管理内存
容易发生内存泄露(忘记释放、出现异常等)
释放之后产生野指针
◼ 智能指针就是为了解决传统指针存在的问题
auto_ptr:属于C++98标准,在C++11中已经不推荐使用(有缺陷,比如不能用于数组)
shared_ptr:属于C++11标准
unique_ptr:属于C++11标准
1.auto_ptr,无须delete,自动调用析构函数,person对象的生命周期跟随智能指针,智能指针处于栈空间,临时变量,在函数结束时销毁,一旦没有智能指针指向person对象,则person对象也销毁
void test(){
// Person *p = new Person();
//可以理解为:只能指针p指向了堆空间的person对象
auto_ptr<Person> p(new Person());
}
class Person {
int m_age;
public:
Person(){
cout << "Person()" << endl;
}
Person(int age):m_age(age){
cout << "Person() m_age:"<< age << endl;
}
~Person(){
cout << "~Person()" << endl;
}
void run(){
cout << "run------" << m_age << endl;
}
};
void test(){
// Person *p = new Person();
//可以理解为:智能指针p指向了堆空间的person对象
auto_ptr<Person> p(new Person(20));
p->run();
}
//输出
Person() m_age:20
run------20
~Person()
作用域
cout << 1 << endl;
{
auto_ptr<Person> p(new Person(20));
p->run();
}
cout << 2 << endl;
//输出
1
Person() m_age:20
run------20
~Person()
2
智能指针不要去指向栈空间的对象,否则易导致两次析构,智能指针设计是用来指向堆空间的对象的,如下两次析构,第一次是作用域内person指向栈空间的对象析构,第二次是智能指针指向的person对象的栈空间析构
cout << 1 << endl;
{
Person person(10);
auto_ptr<Person> p(&person);
p->run();
}
cout << 2 << endl;
//输出
1
Person() m_age:10
run------10
~Person()
042-智能指针(16903,0x1000e2dc0) malloc: *** error for object 0x7ffeefbff4b8: pointer being freed was not allocated
042-智能指针(16903,0x1000e2dc0) malloc: *** set a breakpoint in malloc_error_break to debug
2.自定义智能指针
template <typename T>
class SmartPointer{
private:
T *m_obj;
public:
SmartPointer(T *obj):m_obj(obj){
}
~SmartPointer(){
if (m_obj == nullptr) return;
delete m_obj;
}
};
int main(){
{
SmartPointer<Person> p(new Person(20));
}
getchar();
return 0;
}
//输出
1
Person() m_age:20
~Person()
2
此时如何通过智能指针p调用person对象中的方法呢?p->run();直接调用会报错。
通过运算符重载,重载运算符的功能,用指针运算符->时返回Person *的指针m_obj,即p->run()相当于m_obj->run();
template <typename T>
class SmartPointer{
private:
T *m_obj;
public:
SmartPointer(T *obj):m_obj(obj){
}
~SmartPointer(){
if (m_obj == nullptr) return;
delete m_obj;
}
T *operator->(){
return m_obj;
}
};
int main(){
cout << 1 << endl;
{
SmartPointer<Person> p(new Person(20));
p->run();
}
cout << 2 << endl;
getchar();
return 0;
}
//输出
1
Person() m_age:20
run------20
~Person()
2
智能指针是对传统指针的再次封装,构造时传入对象,里面有一个传统指针m_obj指向传入的对象内存地址,析构时,智能指针p释放掉,传统指针指向的对象内存也释放delete m_obj
调用方法时,通过运算符重载,返回指向对象内存地址的传统指针
智能指针是一个对象,重载了指针运算符后返回一个指针
3.auto_ptr缺陷,不支持数组,不能指向数组
传入数组申请了创建了10个对象,但仅仅只析构了一次
template <typename T>
class SmartPointer{
private:
T *m_obj;
public:
SmartPointer(T *obj):m_obj(obj){
}
~SmartPointer(){
if (m_obj == nullptr) return;
delete m_obj;
}
T *operator->(){
return m_obj;
}
};
int main(){
//传入数组,创建10个person对象,但仅仅只会析构一次
{
SmartPointer<Person> p(new Person[10]);
p->run();
}
getchar();
return 0;
}
//输出
Person()
Person()
Person()
Person()
Person()
Person()
Person()
Person()
Person()
Person()
run------0
~Person()
044-智能指针auto_ptr缺陷(92475,0x1000e2dc0) malloc: *** error for object 0x10048fbb8: pointer being freed was not allocated
044-智能指针auto_ptr缺陷(92475,0x1000e2dc0) malloc: *** set a breakpoint in malloc_error_break to debug
4.shared_ptr
◼ shared_ptr的设计理念 多个shared_ptr可以指向同一个对象,当最后一个shared_ptr在作用域范围内结束时,对象才会被自动释放
cout << 1 << endl;
{
shared_ptr<Person> p4;
{
shared_ptr<Person> p1(new Person(20));
shared_ptr<Person> p2 = p1;
shared_ptr<Person> p3 = p2;
p4 = p3;
}
cout << 2 << endl;
}
cout << 3 << endl;
//输出
1
Person() m_age:20
2
~Person()
3
◼ 可以通过一个已存在的智能指针初始化一个新的智能指针

I.指向单个对象
cout << 1 << endl;
{
shared_ptr<Person> p(new Person(20));
p->run();
}
//输出
1
Person() m_age:20
run------20
~Person()
2
II.指向数组
cout << 1 << endl;
{
shared_ptr<Person> p(new Person[5],[](Person *p){
delete[] p;
});
}
cout << 2 << endl;
//输出
1
Person()
Person()
Person()
Person()
Person()
~Person()
~Person()
~Person()
~Person()
~Person()
2
◼一个shared_ptr会对一个对象产生强引用(strong reference)
◼ 每个对象都有个与之对应的强引用计数,记录着当前对象被多少个shared_ptr强引用着
可以通过shared_ptr的use_count函数获得强引用计数
◼ 当有一个新的shared_ptr指向对象时,对象的强引用计数就会+1
◼ 当有一个shared_ptr销毁时(比如作用域结束),对象的强引用计数就会-1
◼ 当一个对象的强引用计数为0时(没有任何shared_ptr指向对象时),对象就会自动销毁(析构)
III.use_count()获取对象强引用数量,即一个对象有多少个智能指针指向
{
shared_ptr<Person> p4;
{
shared_ptr<Person> p1(new Person(20));
cout << p1.use_count() << endl;
shared_ptr<Person> p2 = p1;
cout << p2.use_count() << endl;
shared_ptr<Person> p3 = p2;
cout << p3.use_count() << endl;
p4 = p3;
cout << p4.use_count() << endl;
}
}
//输出
Person() m_age:20
1
2
3
4
~Person()
指向对象的智能指针销毁一个,use_count就会减一
{
shared_ptr<Person> p4;
{
shared_ptr<Person> p1(new Person(10));
cout << p1.use_count() << endl;//1
shared_ptr<Person> p3;
{
shared_ptr<Person> p2 = p1;
cout << p2.use_count() << endl;//2
p3 = p2;//3
}//2
cout << p3.use_count() << endl;
p4 = p3;//3
cout << p4.use_count() << endl;
}
cout << p4.use_count() << endl;//1
}
//输出
Person() m_age:10
1
2
2
3
1
~Person()
IV.shared_ptr易出现的问题,两次析构,程序崩溃
Person *p = new Person();
{
shared_ptr<Person> p1(p);
}//析构~Person()
{
shared_ptr<Person> p2(p);
}//析构~Person()
//输出
Person()
~Person()
~Person()
045-shared_ptr易出现的问题(79269,0x1000e6dc0) malloc: *** error for object 0x100487ff0: pointer being freed was not allocated
045-shared_ptr易出现的问题(79269,0x1000e6dc0) malloc: *** set a breakpoint in malloc_error_break to debug
V.shared_ptr循环引用的问题:相互持有,始终无法销毁
class Car;
class Person {
public:
shared_ptr<Car> m_car;
Person(){
cout << "Person()" << endl;
}
~Person(){
cout << "~Person()" << endl;
}
};
class Car{
public:
shared_ptr<Person> m_person;
Car(){
cout << "Car()" << endl;
}
~Car(){
cout << "~Car()" << endl;
}
};
int main(){
{
shared_ptr<Person> person(new Person());
shared_ptr<Car> car(new Car());
person->m_car = car;
car->m_person = person;
}
getchar();
return 0;
}
//输出
Person()
Car()

5.weak_ptr
◼ weak_ptr会对一个对象产生弱引用
◼ weak_ptr可以指向对象解决shared_ptr的循环引用问题
class Car;
class Person {
public:
weak_ptr<Car> m_car;
Person(){
cout << "Person()" << endl;
}
~Person(){
cout << "~Person()" << endl;
}
};
class Car{
public:
shared_ptr<Person> m_person;
Car(){
cout << "Car()" << endl;
}
~Car(){
cout << "~Car()" << endl;
}
};
int main(){
{
shared_ptr<Person> person(new Person());
shared_ptr<Car> car(new Car());
person->m_car = car;
car->m_person = person;
}
getchar();
return 0;
}
//输出
Person()
Car()
~Car()
~Person()

若是使用普通指针,自己会写delete,不存在循环引用的问题,循环引用只是针对智能指针引起的
6.unique_ptr
◼ unique_ptr也会对一个对象产生强引用,它可以确保同一时间只有1个指针指向对象
◼ 当unique_ptr销毁时(作用域结束时),其指向的对象也就自动销毁了
◼ 可以使用std::move函数转移unique_ptr的所有权
class Person {
public:
int m_age;
Person(){
cout << "Person()" << endl;
}
Person(int age):m_age(age){
cout << "Person(int age )"<< m_age << endl;
}
~Person(){
cout << "~Person()" << endl;
}
};
int main(){
{
unique_ptr<Person> person(new Person(20));
}
getchar();
return 0;
}
//输出
Person(int age )20
~Person()
不能多个unique_ptr指向同一个对象,会报错
int main(){
{
unique_ptr<Person> person(new Person(20));
unique_ptr<Person> p1(person);
}
getchar();
return 0;
}
//编译报错
Call to implicitly-deleted copy constructor of 'unique_ptr<Person>'
std::move转移智能指针的指向,p1指向person对象,后面转移给p0指向person对象
unique_ptr<Person> p0;
{
//p1强引用着Person对象
unique_ptr<Person> p1(new Person(20));
//转移之后,p0强引用着Person对象
p0 = std::move(p1);
}
网友评论