为什么需要智能指针?
我们知道C++没有类似go、java等语言的GC机制,需要程序员手动释放在函数内部malloc或者new在堆上分配的内存资源,如果忘记释放,机会出现内存泄漏或者野指针的问题。C++ 11的智能指针应运而生,uqiue_ptr 和shared_ptr(auto_ptr已经被弃用).
在没有主动调用delete ptr 释放指针的时候,User对象的析构函数是不会被回调的。
{
User *u1 = new User("lala", 20);
delete u1;
}
智能指针可以保证,对象指针出了自己的作用域(大括号作用域)以后自动delete,不需要手动回收内存.
{
std::unique_ptr ptr1(new User("xjp", 60));
std::cout << ptr1->name << std::endl;
//delete ptr1.get(); 这个行代码注释掉 User对象的析构函数也会被回调
}
ptr1.get()可以获取到原始的指针,但是不需要ptr1.get()->name来访问对象属性,
直接ptr1->name就可以,因为unique_ptr已经重载了->运算符.
1.unique_ptr
放弃原始指针的所有权(release 方法)
Human *h = ptr1.release();
delete h;
返回的原始指针需要手动释放
重置所持有的原始指针(reset方法)
unique_ptr ptr1(new Human("tom", 20));
ptr1.reset(new Human("jerry", 19));
原来所持有的原始指针所指向内存将被自动销毁。
如果使用缺省参数的话,也就是没有任何对象的所有权, 此时仅将内部对象释放, 并置为空
交换原始指针(swap方法)
unique_ptr ptr1(new Human("tom", 20));
unique_ptr ptr2(new Human("jerry", 19));
ptr1.swap(ptr2);
所有权转移(std::move()方法)
unique_ptr ptr1(new Human("tom", 20));
unique_ptr ptr2 = move(ptr1);
cout << *ptr1 << endl; // 执行报错
unique_ptr 不支持拷贝构造函数和赋值运算。
unique_ptr ptr1(new Human("tom", 20));
std::unique_ptr ptr2(ptr1); // 错误, unique_ptr 不支持拷贝构造函数
std::unique_ptr ptr3 = up1; // 错误, unique_ptr 不支持赋值运算
虽然 unique_ptr 不支持拷贝, 但是可以从函数中返回, 甚至返回局部对象. 如下面的代码, 编译器知道要返回的对象即将被销毁, 因此执行一种特殊的"拷贝":
template
std::unique_ptr Clone(const Ty& obj)
{
return std::unique_ptr(new Ty(obj));
}
template
std::unique_ptr Clone(const Ty& obj)
{
std::unique_ptr temp = std::unique_ptr(new Ty(obj));
return temp;
}
unique_ptr 支持管理数组
std::unique_ptr ups(new A[10]);
printf("sizeof(ups) = %d\n", sizeof(ups));
for (int i = 0; i < 10; i++)
{
ups[i] = i;
printf("ups[i] = %d\n", ups[i]);
}
2.shared_ptr
shared_ptr 是一个标准的共享所有权的智能指针, 允许多个指针指向同一个对象. 定义在 memory 文件中(非memory.h), 命名空间为 std 。
shared_ptr 是通过引用计数的机制实现的。
shared_ptr 重载了 -> 和 *` 操作符。