成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

C++ 面試題:循環引用兩個節點相互引用,如何判斷哪個用 shared_ptr?哪個用 weak_ptr?

開發
通過分析對象生命周期控制權,確定shared_ptr和weak_ptr的使用。始終確保至少有一條所有權路徑不形成閉環。

一、回顧循環引用問題

當兩個對象通過 shared_ptr 相互引用時,會產生循環引用問題,導致內存泄漏。因為這兩個對象的引用計數永遠不會變為 0,即使它們在程序的其他部分已經不被使用了。

典型循環引用:

#include <memory>
#include <iostream>
usingnamespace std;

classB; // 前置聲明

classA {
public:
    shared_ptr<B> b_ptr;
    ~A() { cout << "A destroyed" << endl; }
};

classB {
public:
    shared_ptr<A> a_ptr;
    ~B() { cout << "B destroyed" << endl; }
};

voidtest(){
    shared_ptr<A> a = make_shared<A>();
    shared_ptr<B> b = make_shared<B>();
    a->b_ptr = b;
    b->a_ptr = a;
} 
// test結束時,a和b的引用計數均為1,對象未銷毀

解決方案是打破這個循環,通常是讓其中一個對象使用 weak_ptr 指向另一個對象,而另一個對象使用 shared_ptr。這里決定使用 shared_ptr 還是 weak_ptr 的關鍵在于所有權關系的分析。

二、所有權模型與指針選擇

1. 核心原則:所有權決定指針類型

所有權關系指一個對象對另一個對象生命周期的控制權。所有權持有者使用shared_ptr,非所有者使用weak_ptr。

示例:父子節點模型

class Child; 

classParent {
public:
    vector<shared_ptr<Child>> children;
    voidaddChild(shared_ptr<Child> child){
        children.push_back(child);
    }
    ~Parent() { cout << "Parent destroyed" << endl; }
};

classChild {
public:
    weak_ptr<Parent> parent; // 非擁有性引用
    explicitChild(shared_ptr<Parent> p) : parent(p) {}
    ~Child() { cout << "Child destroyed" << endl; }
};

voiddemo(){
    auto parent = make_shared<Parent>();
    auto child = make_shared<Child>(parent);
    parent->addChild(child);
}
// demo結束時,parent引用計數歸零,觸發Child析構

輸出結果:

Parent destroyed
Child destroyed

關鍵點:Parent 擁有 Child,Child 僅引用 Parent。

2. 雙向鏈表的設計取舍

雙向鏈表中,節點間常需雙向引用。為避免循環引用,需明確主從關系。

示例:鏈表節點設計

class Node {
public:
    shared_ptr<Node> next; // 擁有下一個節點
    weak_ptr<Node> prev;   // 非擁有前驅節點
    int data;
    Node(int val) : data(val) {}
    ~Node() { cout << "Node " << data << " destroyed" << endl; }
};

voidbuildList(){
    auto node1 = make_shared<Node>(1);
    auto node2 = make_shared<Node>(2);
    node1->next = node2;
    node2->prev = node1;
}
// buildList結束時,node1和node2的引用計數歸零

輸出結果:

Node 1 destroyed
Node 2 destroyed

設計邏輯:鏈表的構建通常從前向后遍歷,故next持有所有權,prev僅作反向引用。

三、復雜場景的決策策略

1. 多所有者場景

若多個對象共享某資源,需由頂層管理者持有shared_ptr,其余使用weak_ptr。

示例:緩存系統設計

#include <unordered_map>

classCacheManager;

classResource {
public:
    weak_ptr<CacheManager> manager;  // 弱引用管理器
};

classCacheManager : public enable_shared_from_this<CacheManager> {
public:
    voidaddResource(int id){
        resources[id] = make_shared<Resource>();
        resources[id]->manager = shared_from_this();  // 關鍵行
    }
};

說明:CacheManager擁有所有Resource,Resource通過weak_ptr反向引用管理器。

2. 無明確所有權場景

若對象間無明確從屬關系,需重新審視設計或使用雙向weak_ptr。

示例:聊天室和用戶

#include <memory>
#include <vector>
#include <iostream>
usingnamespace std;

classChatRoom;

classUser {
public:
    string name;
    vector<weak_ptr<ChatRoom>> rooms;  // 弱引用聊天室
};

classChatRoom {
public:
    string name;
    vector<weak_ptr<User>> users;  // 弱引用用戶
};

intmain(){
    auto alice = make_shared<User>("Alice");
    auto general = make_shared<ChatRoom>("General");
    return0;
}

說明:用戶(User) 可以加入多個聊天室,聊天室(ChatRoom) 包含多個用戶,但是他們互相并沒有所有權關系,所以使用雙向weak_ptr,用戶和聊天室的生命周期由外部系統管理!

四、實踐中的注意事項

1. weak_ptr 的安全訪問

使用weak_ptr時需通過lock()獲取shared_ptr,并檢查有效性。

void accessParent(shared_ptr<Child> child) {
    if (auto parent = child->parent.lock()) {
        cout << "Parent is alive: " << parent << endl;
    } else {
        cout << "Parent has been destroyed" << endl;
    }
}

2. 循環引用的檢測工具

Valgrind、AddressSanitizer 等工具可輔助檢測內存泄漏。

靜態代碼分析器(如 Clang-Tidy)可識別潛在循環引用。

五、總結

場景特征

推薦策略

示例

明確單向所有權(如父子節點)

所有者用

Parent-Child 模型

雙向依賴但需單向控制

主方向用

雙向鏈表

多對象共享資源

頂層管理用

緩存系統

無明確所有權

重新設計或雙向

聊天室和用戶

核心準則:通過分析對象生命周期控制權,確定shared_ptr和weak_ptr的使用。始終確保至少有一條所有權路徑不形成閉環。

  • 誰管理生命周期,誰用 shared_ptr。
  • 誰僅需引用對方,誰用 weak_ptr。
責任編輯:趙寧寧 來源: CppPlayer
相關推薦

2025-05-28 08:50:00

C++循環引用節點

2025-04-29 08:35:00

2025-06-24 10:00:00

智能指針代碼unique_ptr

2025-06-09 07:55:00

C++引用語言

2025-02-26 01:23:02

C++11Raw代碼

2010-01-15 18:06:20

C++引用

2024-12-04 09:47:26

C++頭文件實現類

2024-12-10 13:00:00

C++引用

2021-10-27 11:00:30

C++語言面試

2011-03-30 17:20:18

C++引用

2024-01-18 10:27:30

C++引用函數

2025-05-20 10:00:00

C++命名空間別名代碼

2025-05-23 08:15:00

C++constexpr字面類型

2010-02-02 10:33:22

C++引用

2024-01-29 16:55:38

C++引用開發

2011-07-20 15:58:53

C++引用

2025-05-26 03:20:00

2019-06-25 10:46:04

Flutter開發APP

2024-04-28 09:26:40

RustRTTI二進制

2011-07-14 23:27:05

C++引用
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 在线视频99 | 成在线人视频免费视频 | 日韩在线免费视频 | 中文字幕高清免费日韩视频在线 | 色视频www在线播放国产人成 | 国产日韩久久 | 色婷婷久久久亚洲一区二区三区 | 亚洲精品成人 | 国产成人精品一区二区三区四区 | 日韩国产欧美 | 国产免费拔擦拔擦8x高清 | 91精品久久久久久久久久入口 | 黄网站在线播放 | 夜夜爽99久久国产综合精品女不卡 | 亚洲久草视频 | 国产一区 日韩 | 亚欧精品一区 | 欧美精品一区二区在线观看 | 国产精品毛片一区二区三区 | 亚洲国产精品久久久久秋霞不卡 | 91一区二区在线观看 | 99在线国产| 2021狠狠天天天| 羞羞视频网站免费观看 | 一级做a | 91嫩草精品| 亚洲av一级毛片 | 久久久精品久久久 | 成人a视频片观看免费 | 99精品国产一区二区三区 | 涩涩视频在线观看 | 国产美女福利在线观看 | 国产精品久久久久久久 | 精品二区| 午夜专区 | 97精品超碰一区二区三区 | 亚洲欧美日韩精品久久亚洲区 | 成人精品久久 | 不卡av电影在线播放 | 天天看天天爽 | 日韩av成人在线观看 |