文章目录
Smart Pointers
- 为了解决**内存泄漏(memory leak)**问题, C++11引入的新机制.
- 使用完后, 这些指针会自动释放, 不需要程序员操作.
- 一共有三个智能指针
- std::unique_ptr - single ownership
- std::shared_ptr - shared ownership
- std::weak_ptr - temp / no ownership
- defined in <memory> header
unique_ptr
#include <iostream>
#include <memory>
using namespace std;
void bar1(Person * p) {
cout<<p->age<<endl;
// delete p; 如果这里释放了, test01函数中p指针就成了一个野指针
}
void bar2(unique_ptr<Person> p) {
cout<<p->age<<endl;
}
void test01() {
Person * p = new Person();
bar1(p);
if (p != NULL) {
cout<<p->age<<endl;
}
// delete p;
}
void test02() {
unique_ptr<Person> p = make_unique<Person>();
bar2(move(p));
if (p == NULL) {
cout<<"NULL pointer"<<endl;
}
}
int main() {
test01();
test02();
return 0;
}
Person created
0
0
Person created
0
Person destroyed
NULL pointer
- unique_ptr 指针指向的内存块只能有一个拥有者, 即只能有一个变量指向它. 使用move函数将所有权转移后, 原来的指针变量就变为NULL.
unique_ptr 构造
- 不能把裸指针肤质给unique_ptr
- unique_ptr<Node> p1 = make_unique<Node>();
- 因为unique_ptr 是single ownership, 所以不能=(拷贝)赋值
- auto p2 = move(p1);
examples
Life Cycle
shared_ptr
- 有一个use_count 引用计数变量. 用来维护该对象被多少指针指向. 通过use_count()成员函数获得
- 最常使用的, 和裸指针的用法相似, 只是这个可以被自动释放.
shared_ptr 构造
- =赋值, use_count 会增加
- move, use_count仍然不变, 原来的变为空指针
examples
- 虽然有多个use_count, 但是对象始终只有一个, make_shared()时创建. 因此整个过程只有最后析构了一个对象.
Life Cycle
weak_ptr
- 使用之前必须转换成shared_ptr, 使用的时候如果原来的shared_ptr还存在, 则正常使用. 否则就不能使用, 也不会报错.
examples
总结
- 在多线程了,使用shared_ptr更新共享资源可能存在竞争条件, 还需要加锁.
使用智能指针写一个链表
- unique_ptr 没有 = 赋值
- 在单线程里 shared_ptr更像原生指针
- get()函数, 获得对象里的原生指针 C++ 11 智能指针详解
#include <iostream>
#include <memory>
using namespace std;
template <typename T>
struct Node {
T val;
// unique_ptr<Node<T>> next;
shared_ptr<Node<T>> next;
Node(){
cout<<"Node"<<val<<endl;
}
~Node(){
cout<<"~Node"<<val<<endl;
}
};
template <typename T>
class Link {
public:
// 头插法
void creatLink(int val){
// auto node = make_unique<Node<T>>();
auto node = make_shared<Node<T>>();
node->val = val;
node->next = move(head.next);
head.next = move(node);
}
void print() {
// Node<int>* node = head.next.get(); // get()方法获得原生指针
// auto node = move(head.next); // 使用的是unique_ptr
shared_ptr<Node<T>> node = head.next;
while(node != NULL) {
cout<<node->val<<endl;
node = node->next;
}
}
Node<T> head;
};
int main() {
Link<int> lk;
for (int val : {1,2,3,4,5}) {
lk.creatLink(val);
}
lk.print();
return 0;
}