c++11新特性:default和delete

  • 2019 年 12 月 25 日
  • 筆記

緣起

今早在美國的本科室友問了我下面的C++程式碼是什麼意思:

#ifdef  _CV_H  #define _CV_H  class cv{  	cv(const cv&) = delete;  	cv& operator=(const cv&) = delete;    	cv(cv&&);  	cv& operator=(cv&&);  };  #endif

什麼,delete居然還有這種神奇的用法?我確實以前沒看過。所以我跑到實驗室,自己查了些資料,大概明白這些程式碼是個什麼意思了,所以記錄下來。

default和delete

在C++03的標準裡面,如果程式程式碼裡面沒有寫默認構造函數(像cv();)、複製構造函數、複製賦值函數(像cv cv2=cv1;)和析構函數,則編譯器會自動添加這些函數。當程式裡面寫了構造函數的時候,編譯器就不會自動添加默認構造函數了。 那如果我想讓一個類的實例不能通過複製構造函數來生成,該怎麼辦呢?一般的方法是將複製構造函數和複製賦值函數聲明為private,而且不去具體實現它們,這樣就達到了目的。 但這樣做其實是很tricky的方式,相當於利用c++的一些特性碰巧來實現,總感覺不是正確的方法。 C++11裡面可以用default來指定使用默認的構造函數,而且可以通過delete來顯式地禁止一些方法,如複製構造函數和複製賦值操作,如下例:

struct NonCopyable{  	NonCopyable() = default;  	NonCopyable(const NonCopyable&) = delete;  	NonCopyable& operator=(const NonCopyable&) = delete;  };

這個例子裡面,第一條語句是強制編譯器生成默認構造函數作為struct的構造函數;第2、3條語句就是顯式地禁用複製構造函數和複製賦值函數。

move constructor

既然禁止了複製構造函數,那麼如果想通過已經生成的類的實例來初始化一個同類的實例,要怎麼操作呢?顯然,cv cv2(cv1)cv cv2=cv1;是不可以用的了,因為複製構造函數已經被禁止了。 C++11新定義了一個叫做move constructor的構造函數,簽名方法如下:

class_name(class_name &&);  class_name& operator=(class_name &&);

調用時這樣用:

class_name c1;  class_name c2=std::move(c1);  class_name c3(std:move(c1));

所謂move,我的理解就是類似於指針一樣的概念,move生成的新的實例和原先的實例是由同一個指針指向的,即實際上是同一個實例。而且&&這個符號讓人聯想到了**,可能也是這個意思吧。 這就是這個新特性的簡單介紹,感覺應用場合不是很多,可能是我還沒搞懂的原因吧。 看了這篇部落格,發現這個新特性還是很強大的啊~還是too young。 從這裡看到,vs2012裡面還不支援這個特性,vs2013才開始支援。在g++中,可以通過使用-std=c++11來啟用這個特性(我用的是g++4.9.2,默認是開啟的)。

參考鏈接: http://blog.csdn.net/pongba/article/details/1684519 https://en.wikipedia.org/wiki/C%2B%2B11#Explicitly_defaulted_and_deleted_special_member_functions http://en.cppreference.com/w/cpp/language/move_constructor http://stackoverflow.com/questions/7421825/c11-features-in-visual-studio-2012 http://stackoverflow.com/questions/6077143/disable-copy-constructor