日本综合一区二区|亚洲中文天堂综合|日韩欧美自拍一区|男女精品天堂一区|欧美自拍第6页亚洲成人精品一区|亚洲黄色天堂一区二区成人|超碰91偷拍第一页|日韩av夜夜嗨中文字幕|久久蜜综合视频官网|精美人妻一区二区三区

RELATEED CONSULTING
相關(guān)咨詢(xún)
選擇下列產(chǎn)品馬上在線溝通
服務(wù)時(shí)間:8:30-17:00
你可能遇到了下面的問(wèn)題
關(guān)閉右側(cè)工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營(yíng)銷(xiāo)解決方案
因?yàn)檫@7個(gè)C++的坑,整個(gè)團(tuán)隊(duì)加班一星期

 近期我們團(tuán)隊(duì)進(jìn)行版本質(zhì)量加固時(shí),踩到了一些比較隱晦的C++的坑,特總結(jié)分享在此,供大家參考。

創(chuàng)新互聯(lián)建站從2013年開(kāi)始,先為濟(jì)寧等服務(wù)建站,濟(jì)寧等地企業(yè),進(jìn)行企業(yè)商務(wù)咨詢(xún)服務(wù)。為濟(jì)寧企業(yè)網(wǎng)站制作PC+手機(jī)+微官網(wǎng)三網(wǎng)同步一站式服務(wù)解決您的所有建站問(wèn)題。

1. string的字符串拼接,導(dǎo)致coredump

該問(wèn)題的核心點(diǎn)在于第9行,竟然是可以編譯通過(guò),其原因是x+"-",會(huì)被轉(zhuǎn)成char*,然后與to_string疊加導(dǎo)致BUG。

2. map的迭代器刪除

map要?jiǎng)h除一個(gè)元素,通常通過(guò)erase()函數(shù)來(lái)完成,但是要注意,如果我們傳入了一個(gè)iterator作為erase的參數(shù)來(lái)刪除當(dāng)前迭代器所指向的元素,刪除完成后iterator會(huì)失效,產(chǎn)生未定義行為。

正確的使用方法應(yīng)該是接收erase()的返回值,讓iterator指向被刪除元素的下一個(gè)元素或者end()。 

 
 
 
 
  1. for  ( auto  iter = m.begin(); iter != m.end(); iter++) {  
  2.   if  (...)  
  3.   iter = m.erase(iter);  
  4.   } 

但是上述代碼仍然有錯(cuò)誤,因?yàn)槿绻|發(fā)了刪除,那么iter再下一輪循環(huán)時(shí)會(huì)指向下下個(gè)元素,所以正確的寫(xiě)法應(yīng)該是: 

 
 
 
 
  1. for  ( auto  iter = m.begin(); iter != m.end();) {  
  2.   if  (...) {  
  3.   iter = m.erase(iter);  
  4.   continue ;  
  5.   }  else  {  
  6.   iter++;  
  7.   }  
  8.   } 

3. stringstream的性能問(wèn)題

  1.  stringstream的清空是clear之后,置空。
  2.  stringstream在任何情況下都比snprintf慢。
  3.  memset是個(gè)很慢的函數(shù),寧愿新創(chuàng)建對(duì)象。
  4.  上述測(cè)試結(jié)果是單線程,改成多線程,同樣成立。
  5.  str += “a”, 比 str =str+ “a” 效率高很多,后者會(huì)創(chuàng)建新對(duì)象。

4. 智能指針(shared_ptr)使用注意

4.1盡量使用make_shared初始化

提高性能 

 
 
 
 
  1. std::shared_ptr spw(newWidget); 

需要分配兩次內(nèi)存。每個(gè)std::shared_ptr都指向一個(gè)控制塊,控制塊包含被指向?qū)ο蟮囊糜?jì)數(shù)以及其他東西。這個(gè)控制塊的內(nèi)存是在std::shared_ptr的構(gòu)造函數(shù)中分配的。因此直接使用new,需要一塊內(nèi)存分配給Widget,還要一塊內(nèi)存分配給控制塊

 
 
 
 
  1. autospw = std::make_shared(); 

一次分配就足夠了。這是因?yàn)閟td::make_shared申請(qǐng)一個(gè)單獨(dú)的內(nèi)存塊來(lái)同時(shí)存放Widget對(duì)象和控制塊。這個(gè)優(yōu)化減少了程序的靜態(tài)大小,因?yàn)榇a只包含一次內(nèi)存分配的調(diào)用,并且這會(huì)加快代碼的執(zhí)行速度,因?yàn)閮?nèi)存只分配了一次。另外,使用std::make_shared消除了一些控制塊需要記錄的信息,這樣潛在地減少了程序的總內(nèi)存占用。

異常安全 

 
 
 
 
  1. processWidget(std::shared_ptr( new  Widget),   //潛在的資源泄露   
  2.   computePriority()); 

上述代碼存在內(nèi)存泄漏的風(fēng)險(xiǎn),上述代碼執(zhí)行分為3個(gè)步驟:

  1.  new  Widget

  2. shared_ptr構(gòu)造

  3. computePriority

編譯器不需要必須產(chǎn)生這樣順序的代碼,但“new Widget”必須在std::shared_ptr的構(gòu)造函數(shù)被調(diào)用前執(zhí)行。如果編譯器產(chǎn)生的順序代碼如下:

  1.  new  Widget

  2. 執(zhí)行computePriority。

  3. 執(zhí)行std::shared_ptr的構(gòu)造函數(shù)。

如果執(zhí)行步驟2:computePriority的時(shí)候程序出現(xiàn)異常,則在第一步動(dòng)態(tài)分配的Widget就會(huì)泄露了,因?yàn)樗肋h(yuǎn)不會(huì)被存放到在第三步才開(kāi)始管理它的shared_ptr中

4.2 父類(lèi)之類(lèi)智能指針轉(zhuǎn)換

C++中是允許裸指針,因此裸指針之間轉(zhuǎn)換方法同C語(yǔ)言指針強(qiáng)轉(zhuǎn),智能指針轉(zhuǎn)換不能通過(guò)上述方法進(jìn)行強(qiáng)轉(zhuǎn),必須通過(guò)庫(kù)提供轉(zhuǎn)換函數(shù)進(jìn)行轉(zhuǎn)換。C++11的方法是:std::dynamic_pointer_cast;boost中的方法是:boost::dynamic_pointer_cast 

 
 
 
 
  1. #include   
  2. #include   
  3. #include   
  4. #include   
  5. class  Base {  
  6.   public :  
  7.   Base(){}  
  8.   virtual  ~Base() {}  
  9. };  
  10. class  D :  public  Base {  
  11.   public :  
  12.   D(){}  
  13.   virtual  ~D() {}  
  14. };  
  15. int  main()  
  16. {  

//方式一:先初始化子類(lèi)智能指針,然后調(diào)用dynamic_pointer_cast轉(zhuǎn)換成基類(lèi)智能指針對(duì)象 

 
 
 
 
  1. std::shared_ptr d1 = std::make_shared();  
  2. std::shared_ptr b1 = std::dynamic_pointer_cast(d1);   

//方式二:先new子類(lèi)D的指針,然后調(diào)用shared_ptr的構(gòu)造函數(shù)初始化基類(lèi)智能指針 

 
 
 
 
  1.   std::shared_ptr b2 = shared_ptr( new  D());  
  2.   return  0;  

結(jié)論

方式一和方式二均能夠?qū)崿F(xiàn)基類(lèi)智能指針指向子類(lèi),但建議采用方式1,通過(guò)std::make_shared的方式構(gòu)造智能指針,然后進(jìn)行轉(zhuǎn)換;

5. map的安全查找辦法

即map[key]這種寫(xiě)法,就是會(huì)創(chuàng)建元素(且不一定初始化),因此在業(yè)務(wù)邏輯是希望查找的時(shí)候,就老老實(shí)實(shí)用find,不然會(huì)有臟數(shù)據(jù)寫(xiě)入。

6. string 的指針構(gòu)造

std::string 的構(gòu)造方式,除了與其它順序容器相近的方式之外,提供了三種額外的構(gòu)造方式:

string s(cp, n): s 是cp指向的數(shù)組中前n個(gè)字符的拷貝,該數(shù)組至少應(yīng)該包含n個(gè)字符

string s(s2, pos2):s 是string s2從下標(biāo)pos2開(kāi)始的字符的拷貝,若pos2>s2.size(),構(gòu)造函數(shù)的行為未定義

string s(s2, pos2, len2):s 是string s2從下標(biāo)pos2開(kāi)始len2個(gè)字符的拷貝,若pos2>s2.size(),構(gòu)造函數(shù)的行為未定義。不管len2的值是多少,構(gòu)造函數(shù)至多拷貝s2.size()-pos2個(gè)字符

std::string 未提供 string(cp, pos2, len2) 這種構(gòu)造方式,如果代碼中使用了該方式,最終會(huì)將 cp 指向的數(shù)組構(gòu)造成一個(gè)string,然后調(diào)用string(s2, pos2, len2)這種構(gòu)造方式。

不提供string(cp, pos2, len2)這種構(gòu)造方式原因在于:使用這種方式構(gòu)造容易出現(xiàn)問(wèn)題,cp是一個(gè)指針,通常使用時(shí),能獲得其數(shù)組長(zhǎng)度并檢查傳入?yún)?shù);若傳入兩個(gè)參數(shù),容易出現(xiàn)越界。

7. 變量初始化

變量初始化總是沒(méi)錯(cuò)的,不管后面是否會(huì)修改該值。尤其是int等內(nèi)建的類(lèi)型,在類(lèi)或struct中及容易忽略初始化,使變量成為隨機(jī)值,產(chǎn)生不可預(yù)知的錯(cuò)誤。變量請(qǐng)初始化!變量請(qǐng)初始化!!變量請(qǐng)初始化!?。?nbsp;


網(wǎng)頁(yè)名稱(chēng):因?yàn)檫@7個(gè)C++的坑,整個(gè)團(tuán)隊(duì)加班一星期
URL地址:http://www.dlmjj.cn/article/cdcodpc.html