欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

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

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

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

規(guī)則

參考Effective Morder C++上的說明:

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

例子:A BUG

因為不熟悉析構(gòu)函數(shù)的生成機制,導(dǎo)致了一個BUG。

首先,下面的代碼沒有問題,因為數(shù)據(jù)成員m_,所以Widget默認也是個只移型別;mm中也可以插入一個由只移型別構(gòu)造的std::pair<int, Widget>,因為pair默認支持右值參數(shù)構(gòu)造(可以由只移的Widget構(gòu)造)和自身的移動構(gòu)造函數(shù)(可以移動構(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òu)函數(shù):

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

報錯信息極長,核心錯誤是:

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)造單獨抽出來看到更清晰的報錯信息:

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

“顯然”,是因為Widget的移動構(gòu)造函數(shù)被隱式刪除了(它既不能拷貝也不能移動了),所以無法由Widget參數(shù)構(gòu)造一個std::pair。

解決方案就是不要定義析構(gòu)函數(shù),或者顯式定義一個移動構(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

在我做試驗的時候,一開始錯把std::mutex記成了只移型別

定義了一個這樣的類:

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

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

看看源碼:

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

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

和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ù),但是它顯式定義了移動構(gòu)造函數(shù),這使得它雖然不能拷貝但是可以移動。

題外話:為什么std::mutex不可移動?

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

詳見stackoverflow: https://stackoverflow.com/questions/7557179/move-constructor-for-stdmutex

總結(jié)

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

相關(guān)文章

  • C++11/14 線程調(diào)用類對象和線程傳參的方法

    C++11/14 線程調(diào)用類對象和線程傳參的方法

    這篇文章主要介紹了C++11/14 線程調(diào)用類對象和線程傳參的方法,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2019-01-01
  • C++基于回溯法解決八皇后問題示例

    C++基于回溯法解決八皇后問題示例

    這篇文章主要介紹了C++基于回溯法解決八皇后問題,簡單描述了八皇后問題,以及回溯法的原理與解決八皇后問題的相關(guān)操作技巧,需要的朋友可以參考下
    2017-11-11
  • C語言技巧提升之回調(diào)函數(shù)的掌握

    C語言技巧提升之回調(diào)函數(shù)的掌握

    這篇文章主要為大家詳細介紹一下C語言中回調(diào)函數(shù)的用法教程,文中的示例代碼講解詳細,對我們學(xué)習(xí)C語言有一定幫助,需要的可以參考一下
    2022-12-12
  • C語言實現(xiàn)雙向鏈表

    C語言實現(xiàn)雙向鏈表

    本文給大家分享的是一段使用C語言實現(xiàn)雙向鏈表的代碼,完全是根據(jù)自己的理解和認識來編寫的,希望大家能夠喜歡,文章的最后附上了一個網(wǎng)友寫的對于雙向鏈表刪除節(jié)點、插入節(jié)點、雙向輸出等操作的代碼,也非常不錯,推薦給大家
    2015-03-03
  • C語言解決字符串中插入和刪除某段字符串問題

    C語言解決字符串中插入和刪除某段字符串問題

    這篇文章主要介紹了C語言解決字符串中插入和刪除某段字符串問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2023-02-02
  • C++中構(gòu)造函數(shù)重載

    C++中構(gòu)造函數(shù)重載

    這篇文章主要介紹了C++中構(gòu)造函數(shù)重載的相關(guān)資料,十分的詳細,需要的朋友可以參考下
    2015-06-06
  • C++ 11實現(xiàn)檢查是否存在特定的成員函數(shù)

    C++ 11實現(xiàn)檢查是否存在特定的成員函數(shù)

    C++11/14相比以往的C++98/03在很多方面做了簡化和增強,尤其是在泛型編程方面,讓C++的泛型編程的威力變得更加強大,下面這篇文章主要介紹了利用C++ 11實現(xiàn)檢查是否存在特定成員函數(shù)的相關(guān)資料,需要的朋友可以參考下。
    2017-02-02
  • c++ #include是怎么樣工作的?

    c++ #include是怎么樣工作的?

    大多數(shù)園友可能對“#include”比較熟悉,因為我們寫C/C++程序的時候都會寫的字符串之一,但是它是具體怎么工作的?或者它的原理是什么呢?
    2013-01-01
  • c++ 數(shù)字類型和字符串類型互轉(zhuǎn)詳解

    c++ 數(shù)字類型和字符串類型互轉(zhuǎn)詳解

    今天小編就為大家分享一篇講解c++ 數(shù)字類型和字符串類型互轉(zhuǎn)的文章,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2021-09-09
  • C++ Qt QColorDialog使用方法

    C++ Qt QColorDialog使用方法

    本文主要介紹了C++ Qt QColorDialog使用方法,文中通過示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-01-01

最新評論