欧美1区2区3区激情无套,两个女人互添下身视频在线观看,久久av无码精品人妻系列,久久精品噜噜噜成人,末发育娇小性色xxxx

C++ 智能指針,高頻面試點(diǎn)整理

  1. 動(dòng)態(tài)內(nèi)存的問(wèn)題/為什么引入智能指針?
  2. 和裸指針相比有什么優(yōu)點(diǎn)?
  3. share_ptr、unique_ptr、weak 的區(qū)別是什么?
  4. 有沒(méi)有看過(guò)shared的實(shí)現(xiàn)?weak解決循環(huán)引用
  5. 如果函數(shù)內(nèi)部有一個(gè)unique,指向一個(gè)對(duì)象,那可以return unique嗎?
  6. 同一個(gè)對(duì)象從unique_ptrA轉(zhuǎn)移到unique_ptrB 怎么做?

什么是動(dòng)態(tài)內(nèi)存?

動(dòng)態(tài)內(nèi)存指程序運(yùn)行時(shí)在堆(heap)上按需分配的內(nèi)存,與編譯時(shí)或函數(shù)調(diào)用時(shí)就確定好大小的“靜態(tài)”或“自動(dòng)”內(nèi)存不同。

動(dòng)態(tài)內(nèi)存的問(wèn)題

可以處理不確定大小或需要靈活管理內(nèi)存,但也會(huì)帶來(lái)問(wèn)題,比如分配內(nèi)存忘記釋放,導(dǎo)致內(nèi)存泄露;指針還在使用就被釋放了,非法訪問(wèn)異常;對(duì)象的聲明周期難以明確。

sahred、unique、weak 的區(qū)別

智能指針的作用就是管理一個(gè)指針,實(shí)際上就是一個(gè)類(lèi),超出類(lèi)的作用域時(shí),調(diào)用析構(gòu)函數(shù)自動(dòng)釋放資源。C++中有shared、unique、weak三種指針。shared允許多個(gè)指針指向同一對(duì)象,而unique獨(dú)占對(duì)象,weak的話(huà)更像是shared的輔助,解決shared的循環(huán)引用問(wèn)題。一個(gè)weak綁定到一個(gè)shared不會(huì)改變shared_ptr的引用計(jì)數(shù)。

shared原理

首先是定義了一個(gè)基類(lèi),shared和unique都繼承這個(gè)基類(lèi),但shared還繼承了一個(gè)引用計(jì)數(shù)的基類(lèi),這個(gè)引用計(jì)數(shù)基類(lèi)提供了一個(gè)引用計(jì)數(shù)機(jī)制,類(lèi)里面有一個(gè)成員變量,這個(gè)成員變量記錄資源的引用計(jì)數(shù),或者叫強(qiáng)引用計(jì)數(shù)。表示有多少個(gè)指針指向該資源,(還有一個(gè)是弱引用計(jì)數(shù))。當(dāng)引用計(jì)數(shù)減少到0時(shí),銷(xiāo)毀資源(并減少弱引用計(jì)數(shù),弱引用計(jì)數(shù)到0時(shí),就會(huì)刪除計(jì)數(shù)的基類(lèi))。

weak解決循環(huán)引用

循環(huán)引用是指兩個(gè)或多個(gè)對(duì)象之間相互引用,形成一個(gè)環(huán)狀結(jié)構(gòu)。在使用智能指針時(shí),特別是 std::shared_ptr 時(shí),如果不注意管理對(duì)象之間的引用關(guān)系,就有可能出現(xiàn)循環(huán)引用,導(dǎo)致內(nèi)存泄漏。這個(gè)循環(huán)引用和死鎖有點(diǎn)類(lèi)似,也是成環(huán)了,A、B相互引用,強(qiáng)引用計(jì)數(shù)沒(méi)辦法為0,資源就不能被釋放,代碼示例如下:

#include <iostream>
#include <memory>

class B;

class A {
public:
    std::shared_ptr<B> b_ptr;
    A() {
        std::cout << "A constructor" << std::endl;
    }
    ~A() {
        std::cout << "A destructor" << std::endl;
    }
};

class B {
public:
    std::shared_ptr<A> a_ptr;
    B() {
        std::cout << "B constructor" << std::endl;
    }
    ~B() {
        std::cout << "B destructor" << std::endl;
    }
};
int main() {
    std::shared_ptr<A> a_ptr = std::make_shared<A>();
    std::shared_ptr<B> b_ptr = std::make_shared<B>();

    // 循環(huán)引用
    a_ptr->b_ptr = b_ptr;
    b_ptr->a_ptr = a_ptr;

    return 0;
}

在這個(gè)示例中,類(lèi) A 和類(lèi) B 分別擁有一個(gè) std::shared_ptr 成員,分別指向?qū)Ψ降膶?duì)象。當(dāng) main 函數(shù)中創(chuàng)建了 A 和 B 的 shared_ptr 對(duì)象后,A 和 B 對(duì)象之間建立了循環(huán)引用關(guān)系。由于 shared_ptr 使用引用計(jì)數(shù)來(lái)管理內(nèi)存,這種循環(huán)引用會(huì)導(dǎo)致對(duì)象的引用計(jì)數(shù)永遠(yuǎn)不會(huì)為零。

 std::cout <<a_ptr.use_count() //打印引用計(jì)數(shù)查看 

解決辦法就是將兩個(gè)類(lèi)中的一個(gè)成員變量改為weak_ptr對(duì)象。

weak解決空懸指針問(wèn)題

有兩個(gè)指針p1和p2,指向堆上的同一個(gè)對(duì)象Object,p1和p2位于不同的線程中。假設(shè)線程A通過(guò)p1指針將對(duì)象銷(xiāo)毀了(盡管把p1置為了NULL),那p2就成了空懸指針。

weak不控制對(duì)象的生命期,但是它知道對(duì)象是否還活著。如果對(duì)象還活著,那么它可以提升為有效的shared(提升操作通過(guò)lock()函數(shù)獲取所管理對(duì)象的強(qiáng)引用指針);如果對(duì)象已經(jīng)死了,提升會(huì)失敗,返回一個(gè)空的shared。

函數(shù)內(nèi)部創(chuàng)建 unique,能否直接作為返回值返回?

可以。unique 支持移動(dòng)語(yǔ)義(std::move),函數(shù)返回時(shí)會(huì)把內(nèi)部的指針“搬走”給調(diào)用者。

std::unique_ptr<MyClass> makeObject() {
    auto ptr = std::make_unique<MyClass>(/*ctor args*/);
    return ptr;              // C++17 起可直接 return ptr; 
    // 或者寫(xiě)作 return std::move(ptr); 在 C++11/14 中同樣有效
}

// 調(diào)用方
auto obj = makeObject();    // obj 接管了 ptr 原來(lái)管理的對(duì)象

如何將同一個(gè)對(duì)象從 unique_ptr A 轉(zhuǎn)移到 unique_ptr B?

使用 std::move(或 release()/reset() 組合)將所有權(quán)移動(dòng)。

std::unique_ptr<MyClass> A = std::make_unique<MyClass>();
// 轉(zhuǎn)移所有權(quán):A 變空(nullptr),B 管理原對(duì)象
std::unique_ptr<MyClass> B = std::move(A);

// 此后:A.get() == nullptr,B.get() 指向原對(duì)象
std::unique_ptr<MyClass> A = std::make_unique<MyClass>();
std::unique_ptr<MyClass> B; 
B.reset(A.release());  // release() 交出原始指針,A 置空,reset() 接管

兩種方式本質(zhì)上都是將底層原始指針的所有權(quán)從 A 轉(zhuǎn)到 B,且 A 最終都變成了空指針,但是更推薦方案 1,因?yàn)榉桨?1 語(yǔ)義清晰,而且:

  • std::move 是原子操作,只會(huì)修改內(nèi)部指針和計(jì)數(shù),不會(huì)拋出異常;
  • release()/reset() 需要先調(diào)用 release() 得到裸指針,若后續(xù)發(fā)生異常(如在 reset() 之前拋),就會(huì)造成內(nèi)存泄漏。

關(guān)于 std::move 在后續(xù) C++11 新特性中有介紹。

#嵌入式面經(jīng)##嵌入式##C++#
嵌入式軟件面試筆記 文章被收錄于專(zhuān)欄

整理高頻考點(diǎn)、匯總常見(jiàn)的面試題庫(kù)、總結(jié)面試中的提問(wèn) 每個(gè)知識(shí)點(diǎn)盡可能做到「 原理 → 擴(kuò)展 」

全部評(píng)論

相關(guān)推薦

評(píng)論
3
5
分享

創(chuàng)作者周榜

更多
牛客網(wǎng)
??推髽I(yè)服務(wù)