一、智能指针
在传统 C++ 里我们只好使用 new 和 delete 去 『记得』对资源进行释放。而 C++11 引入了智能指针的概念,让程序员不再需要关心手动释放内存。1.shared_ptr
引用计数这种计数是为了防止内存泄露而产生的。 基本想法是对于动态分配的对象,进行引用计数,每当增加一次对同一个对象的引用,那么引用对象的引用计数就会增加一次, 每删除一次引用,引用计数就会减一,当一个对象的引用计数减为零时,就自动删除指向的堆内存。2.weak_ptr
weak_ptr是一种不控制所指向对象生存期的智能指针,协助shared_ptr工作,它指向一个由shared_ptr管理的对象。将一个weak_ptr绑定到一个shared_ptr不会改变shared_ptr的引用计数。并且一旦最后一个shared_ptr被销毁,其所指向的对象就会被释放,就算此时仍有weak_ptr指向该对象,也会被释放。struct A;
struct B;
struct A {
std::shared_ptr<B> pointer;
~A() {
std::cout << "A 被销毁" << std::endl;
}
};
struct B {
std::shared_ptr<A> pointer;
~B() {
std::cout << "B 被销毁" << std::endl;
}
};
int main() {
auto a = std::make_shared<A>();
auto b = std::make_shared<B>();
a->pointer = b;
b->pointer = a;
}
上述例子,讲述的一个循环引用导致内存不能释放的问题
a和b两个结构体指针,在内部都有一个指向对方的指针,因此A和B的空间计数都是2,在程序结束时,仅仅是把两个计数都减一,引用计数不为0,因此并不会真正释放空间
struct A;
struct B;
struct A {
std::shared_ptr<B> pointer;
~A() {
std::cout << "A 被销毁" << std::endl;
}
};
struct B {
std::weak_ptr<A> pointer;
~B() {
std::cout << "B 被销毁" << std::endl;
}
};
int main() {
auto a = std::make_shared<A>();
auto b = std::make_shared<B>();
a->pointer = b;
b->pointer = a;
}
weak_ptr仅仅是弱引用,因此最终A的计数会变成0,进行释放空间,B也会被释放
3.unique_ptr
一种独占的智能指针,它禁止其他智能指针与其共享同一个对象,unique_ptr对象始终是关联的原始指针的唯一所有者。我们无法复制unique_ptr对象,它只能移动,因此同一时间只会有一个对象可操作来保证安全//初始化
std::unique_ptr<Task> taskPtr(new Task(22));
std::unique_ptr<Task> taskPtr = std::make_unique<Task>(34);
//转移
std::unique_ptr<Task> taskPtr2(new Task(55));
std::unique_ptr<Task> taskPtr4 = std::move(taskPtr2);
此时taskPtr2为空
// 编译错误 : unique_ptr 不能复制
std::unique_ptr<Task> taskPtr3 = taskPtr2; // Compile error
// 编译错误 : unique_ptr 不能复制
taskPtr = taskPtr2; //compile error