最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

C++類的特種函數(shù)生成機(jī)制詳解

 更新時(shí)間:2021年09月14日 11:54:18   作者:saddlesad  
這篇文章主要給大家介紹了關(guān)于C++類特種函數(shù)的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來(lái)一起學(xué)習(xí)學(xué)習(xí)吧

C++類的特種函數(shù)生成機(jī)制

規(guī)則

參考Effective Morder C++上的說(shuō)明:

  • 默認(rèn)構(gòu)造函數(shù):僅當(dāng)類中不包含用戶聲明的構(gòu)造函數(shù)時(shí)才生成。
  • 析構(gòu)函數(shù):默認(rèn)生成,當(dāng)基類的析構(gòu)函數(shù)為虛時(shí),派生類的默認(rèn)析構(gòu)函數(shù)為虛函數(shù)。
  • 拷貝構(gòu)造函數(shù):僅當(dāng)類中不包含用戶聲明的拷貝構(gòu)造函數(shù)時(shí)才生成。如果該類聲明了移動(dòng)操作,那么拷貝構(gòu)造函數(shù)將被定義為刪除的。
  • 拷貝賦值運(yùn)算符:僅當(dāng)類中不包含用戶聲明的拷貝賦值運(yùn)算符時(shí)才生成。如果該類聲明了移動(dòng)操作,那么拷貝賦值運(yùn)算符將被定義為刪除的。
  • 移動(dòng)構(gòu)造函數(shù)和移動(dòng)賦值運(yùn)算符:僅當(dāng)類中不包含用戶聲明的拷貝操作、移動(dòng)操作和析構(gòu)函數(shù)時(shí)才生成。

例子:A BUG

因?yàn)椴皇煜の鰳?gòu)函數(shù)的生成機(jī)制,導(dǎo)致了一個(gè)BUG。

首先,下面的代碼沒(méi)有問(wèn)題,因?yàn)閿?shù)據(jù)成員m_,所以Widget默認(rèn)也是個(gè)只移型別;mm中也可以插入一個(gè)由只移型別構(gòu)造的std::pair<int, Widget>,因?yàn)閜air默認(rèn)支持右值參數(shù)構(gòu)造(可以由只移的Widget構(gòu)造)和自身的移動(dòng)構(gòu)造函數(shù)(可以移動(dòng)構(gòu)造到unordered_map中):

class Widget {
public:
    Widget() = default;
//    ~Widget() = default;
private:
    std::thread m_; // 只移型別
};
unordered_map<int, Widget> mm;
mm.insert({12, Widget()});

然后,我手賤加了一個(gè)默認(rèn)的析構(gòu)函數(shù):

class Widget {
public:
    Widget() = default;
    ~Widget() = default;
private:
    std::thread m_; // 只移型別
};
unordered_map<int, Widget> mm;
mm.insert({12, Widget()}); // error!

報(bào)錯(cuò)信息極長(zhǎng),核心錯(cuò)誤是:

error: no matching function for call to ‘std::unordered_map<int, Widget>::insert(<brace-enclosed initializer list>)'
   45 |     unordered_map<int, Widget> mm;

可以把std::pair的構(gòu)造單獨(dú)抽出來(lái)看到更清晰的報(bào)錯(cuò)信息:

// 代碼如下:
make_pair(12, Widget());
// 報(bào)錯(cuò)如下:
In template: no matching constructor for initialization of '__pair_type' (aka 'pair<int, Widget>')

“顯然”,是因?yàn)閃idget的移動(dòng)構(gòu)造函數(shù)被隱式刪除了(它既不能拷貝也不能移動(dòng)了),所以無(wú)法由Widget參數(shù)構(gòu)造一個(gè)std::pair。

解決方案就是不要定義析構(gòu)函數(shù),或者顯式定義一個(gè)移動(dòng)構(gòu)造函數(shù):

class Widget {
public:
    Widget() = default;
    Widget(Widget&&) = default;
    ~Widget() = default;
private:
    std::thread m_; // 只移型別
};
unordered_map<int, Widget> mm;
mm.insert({12, Widget()});

例子:std::mutex和std::thread

在我做試驗(yàn)的時(shí)候,一開(kāi)始錯(cuò)把std::mutex記成了只移型別

定義了一個(gè)這樣的類:

class Widget {
public:
    Widget() = default;
private:
    std::mutex m_;
};
unordered_map<int, Widget> mm;
mm.insert({12, Widget()}); // error!

甚至在我沒(méi)有添加析構(gòu)函數(shù)的時(shí)候Widget就不能拷貝和移動(dòng)了。

看看源碼:

class mutex : private __mutex_base
{
  public:
    /* ... */
    mutex() noexcept = default;
    ~mutex() = default;
    mutex(const mutex&) = delete;
    mutex& operator=(const mutex&) = delete;
	  /* ... */
}

顯然,因?yàn)閙utex自行定義了默認(rèn)的析構(gòu)函數(shù)而且把拷貝構(gòu)造函數(shù)定義為刪除的,那么它的移動(dòng)構(gòu)造函數(shù)也會(huì)被隱式刪除,所以mutex既不能拷貝也不能移動(dòng)。

和std::thread源碼比較一下:

class thread
{
  public:
  thread() noexcept = default;
  thread(const thread&) = delete;
  thread(thread&& __t) noexcept
  { 
    swap(__t);
  }
  ~thread()
  {
    if (joinable())
      std::terminate();
  }
}

雖然std::thread定義了析構(gòu)函數(shù)和刪除的拷貝構(gòu)造函數(shù),但是它顯式定義了移動(dòng)構(gòu)造函數(shù),這使得它雖然不能拷貝但是可以移動(dòng)。

題外話:為什么std::mutex不可移動(dòng)?

大體來(lái)說(shuō)就是std::mutex一般由多個(gè)線程調(diào)用,那么如果它的位置可以變化,那么怎么讓所有線程都知道它的新位置在哪里呢?

詳見(jiàn)stackoverflow: https://stackoverflow.com/questions/7557179/move-constructor-for-stdmutex

總結(jié)

本篇文章就到這里了,希望能夠給你帶來(lái)幫助,也希望您能夠多多關(guān)注腳本之家的更多內(nèi)容!

相關(guān)文章

  • c語(yǔ)言中如何修改文件中間的幾個(gè)字節(jié)

    c語(yǔ)言中如何修改文件中間的幾個(gè)字節(jié)

    工作中碰到一個(gè)問(wèn)題,如何只修改文件中間的幾個(gè)字節(jié),而其他的內(nèi)容不變。這個(gè)問(wèn)題看似簡(jiǎn)單,但是很多人估計(jì)都不知道怎么做。我開(kāi)始seek到文件的特定的位置,然后寫文件,但是使用的文件打開(kāi)模式不對(duì),文件不是被清空,就是被截?cái)啵_(dá)不到效果
    2020-10-10
  • C++ boost::asio編程-域名解析詳細(xì)介紹

    C++ boost::asio編程-域名解析詳細(xì)介紹

    這篇文章主要介紹了C++ boost::asio編程-域名解析詳細(xì)介紹的相關(guān)資料,這里附有實(shí)例代碼,幫助大家學(xué)習(xí)理解這部分知識(shí),需要的朋友可以參考下
    2016-11-11
  • C++中如何將operator==定義為類的成員函數(shù)

    C++中如何將operator==定義為類的成員函數(shù)

    這篇文章主要介紹了C++中如何將operator==定義為類的成員函數(shù),具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-01-01
  • 深入淺析STL vector用法

    深入淺析STL vector用法

    這篇文章給大家介紹 stl vector用法,主要知識(shí)點(diǎn)在如何恰當(dāng)?shù)氖褂盟鼈兊某蓡T函數(shù),涉及到條件函數(shù)和函數(shù)指針在迭代算法中的使用,對(duì)stl vector用法感興趣的朋友可以參考下本文
    2015-10-10
  • C++示例講解初始化列表方法

    C++示例講解初始化列表方法

    這篇文章主要介紹了C++成員初始化列表,除了可以使用構(gòu)造函數(shù)對(duì)類成員進(jìn)行初始化之外,C++還提供了另外一種初始化的方法,叫做成員初始化列表。下面來(lái)看看文章的詳細(xì)吧,需要的朋友可以參考一下
    2022-07-07
  • C語(yǔ)言中結(jié)構(gòu)體變量私有化詳解

    C語(yǔ)言中結(jié)構(gòu)體變量私有化詳解

    結(jié)構(gòu)是由基本數(shù)據(jù)類型構(gòu)成的、并用一個(gè)標(biāo)識(shí)符來(lái)命名的各種變量的組合,下面這篇文章主要給大家介紹了關(guān)于C語(yǔ)言中結(jié)構(gòu)體變量私有化的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2018-07-07
  • C++模板超詳細(xì)介紹

    C++模板超詳細(xì)介紹

    C++語(yǔ)言的模板技術(shù)包括函數(shù)模板和類模板,模板技術(shù)是一種代碼重用技術(shù),函數(shù)和類是C++語(yǔ)言中兩種主要的重用代碼形式,這篇文章主要介紹了C++函數(shù)模板和類模板,需要的朋友可以參考下
    2022-09-09
  • C++智能指針詳解

    C++智能指針詳解

    從比較簡(jiǎn)單的層面來(lái)看,智能指針是RAII(Resource Acquisition Is Initialization,資源獲取即初始化)機(jī)制對(duì)普通指針進(jìn)行的一層封裝。這樣使得智能指針的行為動(dòng)作像一個(gè)指針,本質(zhì)上卻是一個(gè)對(duì)象,這樣可以方便管理一個(gè)對(duì)象的生命周期
    2022-08-08
  • C語(yǔ)言生成隨機(jī)數(shù)以及設(shè)置隨機(jī)數(shù)范圍的方法(超詳細(xì))

    C語(yǔ)言生成隨機(jī)數(shù)以及設(shè)置隨機(jī)數(shù)范圍的方法(超詳細(xì))

    文章介紹了C語(yǔ)言中生成隨機(jī)數(shù)的方法,包括使用`rand`和`srand`函數(shù),以及如何通過(guò)`time`函數(shù)設(shè)置隨機(jī)種子以確保每次運(yùn)行程序生成的隨機(jī)數(shù)序列不同,此外,還詳細(xì)講解了如何根據(jù)需要設(shè)置隨機(jī)數(shù)的范圍,需要的朋友可以參考下
    2025-02-02
  • C語(yǔ)言實(shí)現(xiàn)棧及棧的詳解

    C語(yǔ)言實(shí)現(xiàn)棧及棧的詳解

    這篇文章主要介紹了C語(yǔ)言實(shí)現(xiàn)棧及棧的詳解,一種特殊的線性表,其只允許在固定的一端進(jìn)行插入和刪除元素操作,進(jìn)行數(shù)據(jù)插入和刪除操作的一端稱為棧頂,另一端稱為棧底,需要的朋友可以參考下
    2023-07-07

最新評(píng)論

柏乡县| 满城县| 通榆县| 吉隆县| 祥云县| 轮台县| 溧水县| 东阳市| 应用必备| 根河市| 墨江| 迭部县| 禄丰县| 山西省| 邛崃市| 嵩明县| 墨竹工卡县| 垣曲县| 哈尔滨市| 新津县| 清水县| 黄大仙区| 略阳县| 年辖:市辖区| 江永县| 朔州市| 盐池县| 剑川县| 金门县| 红桥区| 城口县| 贵溪市| 大渡口区| 嘉荫县| 民勤县| 神农架林区| 望江县| 郑州市| 本溪| 乐都县| 印江|