| 定义智能指针是对象,不是指针。它是通过c++的RAII机制实现的,主要是利用c++对象在释放资源的时候,会自动调用析构函数这一特性。 分类auto_ptr: 智能指针,c++11已经停用;
 shared_ptr: 强智能指针,可以改变资源的引用计数;
 weak_ptr: 弱智能指针,不会改变资源的引用计数;
 unique_ptr: 独占式强智能指针,只能转移,不能重新赋值;
 智能指针的使用shared_ptr
原理 shared_ptr采用了引用计数器,允许多个指针指向同一个对象。每一个shared_ptr的拷贝都指向相同的内存,并共同维护同一个引用计数器,记录统一使用被引用的次数。每增加一个shared_ptr智能指针对象,new对象指针的引用计数上就加1,当shared_ptr智能指针失效时,new对象指针的引用计数就减1。引用计数归0时,shared_ptr会释放管理的内存空间。
 shared_ptr包含2个指针,一个是指向管理的内存空间,一个是指向内存的控制块。
 内存控制块包含引用计数器,删除器,分配器等。 class Test
{
public:
    Test();
    ~Test();
    void setFather(std::shared_ptr<Test> &value) {
        m_father = value;
    }
    void setSon(std::shared_ptr<Test> &value) {
        m_son = value;
    }
private:
    std::shared_ptr<Test> m_father;
    std::shared_ptr<Test> m_son;
};
void test() {
    Test *ps = new Test();
    std::shared_ptr<Test> ptr1(ps);
    std::shared_ptr<Test> ptr2(ps);
    ptr1->setFather(ptr2);
    ptr2->setSon(ptr1);
    //计数
    std::cout << ptr1.use_count() << endl;
    //计数
    std::cout << ptr2.use_count() << endl;
    //计数获取原始指针
    std::cout << ptr1.get() <<endl;
    std::cout << ptr2.get() <<endl;
}
输出:
Test Construct()
2
2
0xfe1740
0xfe1740
 从输出信息中可以看到并未调用析构函数。主要是因为互相引用导致。 示例2 测试引用计数问题 //测试shared_ptr的引用计数
void testSharedPtrCount() {
    //不要使用该方式初始化
    Test *ps = new Test();
    std::shared_ptr<Test> ptr1(ps);
    std::shared_ptr<Test> ptr2(ps);
    //计数
    std::cout << ptr1.use_count() << endl;
    std::cout << ptr2.use_count() << endl;
    std::shared_ptr<Test> ptr3(new Test());
    std::shared_ptr<Test> ptr4 = ptr3;
    //计数
    std::cout << ptr3.use_count() << endl;
    std::cout << ptr4.use_count() << endl;
}
输出:
1
1
2
2
 可以看到使用同一个对象指针初始化的时候,引用计数为1,而使用智能指针初始化智能指针后,引用计数均为2。  
 智能指针的头文件为:#include  weak_ptr
weak_ptr不能单独作为智能指针使用,只能辅助shared_ptr解决循环依赖的问题。
 定义对象的时候使用shared_ptr,引用对象的时候使用weak_ptr。 修改shared_ptr的代码为: class Test
{
public:
    Test();
    ~Test();
    void setFather(std::shared_ptr<Test> &value) {
        m_father = value;
    }
    void setSon(std::shared_ptr<Test> &value) {
        m_son = value;
    }
private:
    //修改对象的引用为weak_ptr
    std::weak_ptr<Test> m_father;
    std::weak_ptr<Test> m_son;
};
输出:
Test Construct()
1
1
0x1091740
0x1091740
Test Destruct()
Test Destruct()
 可以看到析构函数被调用了。(即使析构了2次,部分编译器可能不会出现析构错误信息) unique_ptr
unique_ptr是独占型的强智能指针。独占型就是不允许多个智能指针指向同一块内存空间,也不支持拷贝,复制。
 示例1 独占性 //测试uniqueptr
void testUniquePtr() {
    Test *ps = new Test();
    std::unique_ptr<Test> ptr1(ps);
    //编译期间就出现错误
    std::unique_ptr<Test> ptr2 = ptr1;
    std::cout << ptr1.get() << endl;
    std::cout << ptr2.get() << endl;
}
 **示例2 move ** //测试unique_ptr的转移
void testUniquePtrMove() {
    Test *ps = new Test();
    std::unique_ptr<Test> ptr1(ps);
    std::cout << "Ptr1: " << ptr1.get() << endl;
    std::unique_ptr<Test> ptr2(ps);
    ptr2 = std::move(ptr1);
     std::cout << "Ptr1: "  << ptr1.get() << endl;
     std::cout << "Ptr2: "  << ptr2.get() << endl;
}
//输出
Test Construct()
Ptr1: 0x761740
Test Destruct()
Ptr1: 0
Ptr2: 0x761740
Test Destruct()
 可以看出调用move()后,ptr1被置为nullptr(0),ptr2被设置为0x761740。 常见的陷阱 不要使用指针初始化多个智能指针。 不要delete get()返回的指针。
 总结智能指针是对象而不是指针。智能指针解决的是动态内存管理的问题(堆内存)。shared_ptr的循环依赖问题通过weak_ptr来解决,weak_ptr不拥有对象的所有权,一个share_ptr可对应多个weak_ptr。unique_ptr可算作auto_ptr的翻版,不允许多个unique_ptr持有同一个对象。auto_ptr已经被弃用。
 参考地址C++ 智能指针 c++智能指针 C++智能指针的使用(非常详细) C++智能指针详解 |