智能指针shared_ptr的用法
2016-12-03 15:39
288 查看
为了解决C++内存泄漏的问题,C++11引入了智能指针(Smart Pointer)。
智能指针的原理是,接受一个申请好的内存地址,构造一个保存在栈上的智能指针对象,当程序退出栈的作用域范围后,由于栈上的变量自动被销毁,智能指针内部保存的内存也就被释放掉了(除非将智能指针保存起来)。
C++11提供了三种智能指针:std::shared_ptr, std::unique_ptr, std::weak_ptr,使用时需添加头文件<memory>。
shared_ptr使用引用计数,每一个shared_ptr的拷贝都指向相同的内存。每使用他一次,内部的引用计数加1,每析构一次,内部的引用计数减1,减为0时,删除所指向的堆内存。shared_ptr内部的引用计数是安全的,但是对象的读取需要加锁。
shared_ptr的基本用法
初始化
可以通过构造函数、std::make_shared<T>辅助函数和reset方法来初始化shared_ptr:
注意,不能将一个原始指针直接赋值给一个智能指针,如下所示,原因是一个是类,一个是指针。
reset()有两种操作。当智能指针中有值的时候,调用reset()会使引用计数减1.当调用reset(new xxx())重新赋值时,智能指针首先是生成新对象,然后将就对象的引用计数减1(当然,如果发现引用计数为0时,则析构旧对象),然后将新对象的指针交给智能指针保管。
获取原始指针
指定删除器
智能指针可以指定删除器,当智能指针的引用计数为0时,自动调用指定的删除器来释放内存。std::shared_ptr可以指定删除器的一个原因是其默认删除器不支持数组对象,这一点需要注意。
2. 使用shared_ptr需要注意的问题
但凡一些高级的用法,使用时都有不少陷阱。
不要用一个原始指针初始化多个shared_ptr,原因在于,会造成二次销毁,如下所示:
不要在函数实参中创建shared_ptr。因为C++的函数参数的计算顺序在不同的编译器下是不同的。正确的做法是先创建好,然后再传入。
禁止通过shared_from_this()返回this指针,这样做可能也会造成二次析构。
避免循环引用。智能指针最大的一个陷阱是循环引用,循环引用会导致内存泄漏。解决方法是AStruct或BStruct改为weak_ptr。
智能指针的原理是,接受一个申请好的内存地址,构造一个保存在栈上的智能指针对象,当程序退出栈的作用域范围后,由于栈上的变量自动被销毁,智能指针内部保存的内存也就被释放掉了(除非将智能指针保存起来)。
C++11提供了三种智能指针:std::shared_ptr, std::unique_ptr, std::weak_ptr,使用时需添加头文件<memory>。
shared_ptr使用引用计数,每一个shared_ptr的拷贝都指向相同的内存。每使用他一次,内部的引用计数加1,每析构一次,内部的引用计数减1,减为0时,删除所指向的堆内存。shared_ptr内部的引用计数是安全的,但是对象的读取需要加锁。
shared_ptr的基本用法
初始化
可以通过构造函数、std::make_shared<T>辅助函数和reset方法来初始化shared_ptr:
#include "stdafx.h" #include <iostream> #include <future> #include <thread> using namespace std; class Person { public: Person(int v) { value = v; std::cout << "Cons" <<value<< std::endl; } ~Person() { std::cout << "Des" <<value<< std::endl; } int value; }; int main() { std::shared_ptr<Person> p1(new Person(1));// Person(1)的引用计数为1 std::shared_ptr<Person> p2 = std::make_shared<Person>(2); p1.reset(new Person(3));// 首先生成新对象,然后引用计数减1,引用计数为0,故析构Person(1) // 最后将新对象的指针交给智能指针 std::shared_ptr<Person> p3 = p1;//现在p1和p3同时指向Person(3),Person(3)的引用计数为2 p1.reset();//Person(3)的引用计数为1 p3.reset();//Person(3)的引用计数为0,析构Person(3) return 0; }
注意,不能将一个原始指针直接赋值给一个智能指针,如下所示,原因是一个是类,一个是指针。
std::shared_ptr<int> p4 = new int(1);// error
reset()有两种操作。当智能指针中有值的时候,调用reset()会使引用计数减1.当调用reset(new xxx())重新赋值时,智能指针首先是生成新对象,然后将就对象的引用计数减1(当然,如果发现引用计数为0时,则析构旧对象),然后将新对象的指针交给智能指针保管。
获取原始指针
std::shared_ptr<int> p4(new int(5)); int *pInt = p4.get();
指定删除器
智能指针可以指定删除器,当智能指针的引用计数为0时,自动调用指定的删除器来释放内存。std::shared_ptr可以指定删除器的一个原因是其默认删除器不支持数组对象,这一点需要注意。
2. 使用shared_ptr需要注意的问题
但凡一些高级的用法,使用时都有不少陷阱。
不要用一个原始指针初始化多个shared_ptr,原因在于,会造成二次销毁,如下所示:
int *p5 = new int; std::shared_ptr<int> p6(p5); std::shared_ptr<int> p7(p5);// logic error
不要在函数实参中创建shared_ptr。因为C++的函数参数的计算顺序在不同的编译器下是不同的。正确的做法是先创建好,然后再传入。
function(shared_ptr<int>(new int), g());
禁止通过shared_from_this()返回this指针,这样做可能也会造成二次析构。
避免循环引用。智能指针最大的一个陷阱是循环引用,循环引用会导致内存泄漏。解决方法是AStruct或BStruct改为weak_ptr。
struct AStruct; struct BStruct; struct AStruct { std::shared_ptr<BStruct> bPtr; ~AStruct() { cout << "AStruct is deleted!"<<endl; } }; struct BStruct { std::shared_ptr<AStruct> APtr; ~BStruct() { cout << "BStruct is deleted!" << endl; } }; void TestLoopReference() { std::shared_ptr<AStruct> ap(new AStruct); std::shared_ptr<BStruct> bp(new BStruct); ap->bPtr = bp; bp->APtr = ap; }
相关文章推荐
- C++中的智能指针(1):shared_ptr 的介绍和用法
- 智能指针 shared_ptr 的用法误区.
- 智能指针shared_ptr的用法
- 智能指针shared_ptr的用法
- 智能指针shared_ptr的用法
- c++中关于智能指针std::tr1::shared_ptr的用法
- 智能指针之shared_ptr
- C++ TR1 智能指针shared_ptr的使用(转)
- C++11 FAQ中文版:共享资源的智能指针——shared_ptr
- 智能指针shared_ptr
- 智能指针shared_ptr
- 智能指针之shared_ptr
- STL中的auto_ptr智能指针用法(转)
- C++:智能指针-TR1的shared_ptr和weak_ptr使用介绍
- 智能指针 shared_ptr
- 浅析boost之智能指针—shared_ptr
- Boost智能指针——scoped_ptr和shared_ptr
- Boost智能指针——shared_ptr
- 多索引容器boost::multi_index_container储存共享智能指针boost::shared_ptr
- Boost智能指针——shared_ptr