weak_ptr 与 一个难发现的错误(循环依赖问题)笔记

推荐B站视频:7.weak_ptr与一个非常难发现的错误_哔哩哔哩_bilibiliicon-default.png?t=N7T8https://www.bilibili.com/video/BV18B4y187uL/?p=7&spm_id_from=pageDriver&vd_source=a934d7fc6f47698a29dac90a922ba5a3一、weak_ptr    

  • weak_ptr并不拥有所有权
  • 并不能调用 -> 和 解引用*

准备好头文件和源文件:

  • cat.h
#ifndef CAT_H
#define CAT_H
#include 
#include 
class Cat{
public:
    Cat(std::string name);
    Cat() = default;
    ~Cat();
    void catInfo() const {
        std::cout<<"cat info name : "<m_name = name;
    }
private:
    std::string m_name{"Mimi"};
};
#endif
  • cat.cpp
#include "cat.h"
Cat::Cat(std::string name) :m_name(name) {
    std::cout<<"Constructor of Cat : "<
  • main.cpp
#include 
#include 
#include "cat.h"
using namespace std;
int main(int argc,char* argv[]) {
    std::shared_ptr s_p_c1 = std::make_shared("c1");
    std::weak_ptr w_p_c1(s_p_c1);
    // use_count()
    cout<<"w_p_c1: " << w_p_c1.use_count() << endl; // 1
    cout<<"s_p_c1: " << s_p_c1.use_count() << endl; // 1
    // w_p_c1->catInfo();// error C2039: "catInfo": 不是 "std::weak_ptr" 的成员

    std::shared_ptr s_p_c2 = w_p_c1.lock();
    cout<<"w_p_c1: " << w_p_c1.use_count() << endl; // 2
    cout<<"s_p_c1: " << s_p_c1.use_count() << endl; // 2
    cout<<"s_p_c2: " << s_p_c2.use_count() << endl; // 2

    cout<<"over~"<

二、一个难发现的错误(循环依赖问题

(1)weak_ptr   为什么会存在呢?

  • A类中有一个需求需要存储其他A类对象的信息
  • 如果使用shared_ptr,那么在销毁时会遇到循环依赖问题(Cyclic dependency problem)
  • 所以我们这里需要用一个不需要拥有所有权的指针来标记该同类对象
    • weak_ptr可以通过lock()函数来提升为shared_ptr(类型转换)

比方说我是一个Person,需要存储朋友的信息,需要用一个指针来指向另外一个人类,如果使用shared_ptr,那么在销毁时会遇到循环依赖问题(Cyclic dependency problem)。我在销毁的时候,我需要销毁我的朋友,我的朋友也需要销毁我,这样就出现了循环依赖问题。不知道谁先销毁,谁后销毁。所以我们这里需要用一个不需要拥有所有权的指针来标记该同类对象。

修改头文件cat.h

#ifndef CAT_H
#define CAT_H
#include 
#include 
#include 
class Cat{
public:
    Cat(std::string name);
    Cat() = default;
    ~Cat();
    void catInfo() const {
        std::cout<<"cat info name : "<m_name = name;
    }
    void set_friend(std::shared_ptr cat) {   // 增加该函数
        m_friend = cat;
    }
private:
    std::string m_name{"Mimi"};
    std::shared_ptr m_friend; // 增加该变量
};
#endif

main.cpp

#include 
#include 
#include "cat.h"
using namespace std;
int main(int argc,char* argv[]) {
    std::shared_ptr c3 = std::make_shared("C3");
    std::shared_ptr c4 = std::make_shared("C4");
    cout<<"over~"<

 执行结果,可以正常调用析构函数:

PS D:\Work\C++UserLesson\cppenv\bin\Debug> ."D:/Work/C++UserLesson/cppenv/bin/Debug/app.exe"
Constructor of Cat : C3
Constructor of Cat : C4
over~
Destructor of Cat
Destructor of Cat
PS D:\Work\C++UserLesson\cppenv\bin\Debug>

 可是如果让C3和C4互为朋友

#include 
#include 
#include "cat.h"
using namespace std;
int main(int argc,char* argv[]) {
    std::shared_ptr c3 = std::make_shared("C3");
    std::shared_ptr c4 = std::make_shared("C4");

    c3->set_friend(c4);
    c4->set_friend(c3);
    cout<<"over~"<

执行结果,发现无法正常调用析构函数:

PS D:\Work\C++UserLesson\cppenv\bin\Debug> ."D:/Work/C++UserLesson/cppenv/bin/Debug/app.exe"
Constructor of Cat : C3
Constructor of Cat : C4
over~
PS D:\Work\C++UserLesson\cppenv\bin\Debug>

 (2)解决方案:将头文件的m_friendshared_ptr修改成weak_ptr即可

std::shared_ptr m_friend; 
        ||
        ||  (修改成这样)
        ||
std::weak_ptr m_friend; 

执行结果,发现可以正常调用析构函数:

PS D:\Work\C++UserLesson\cppenv\bin\Debug> ."D:/Work/C++UserLesson/cppenv/bin/Debug/app.exe"
Constructor of Cat : C3
Constructor of Cat : C4
over~
Destructor of Cat
Destructor of Cat
PS D:\Work\C++UserLesson\cppenv\bin\Debug>

你可能感兴趣的:(智能指针,weak_ptr,一个难发现的错误,笔记,shared_ptr)