C 的16个大坑,你能躲过几个?
首先說下C 和C語言有什么區(qū)別?分享一個(gè)我在知乎上看見的回答:
C ≈ C with classes, C with STL
C:面向機(jī)器編程
C :面向編譯器編程
C 有個(gè)很重要的特性叫RAII,個(gè)人認(rèn)為可以多多使用,相當(dāng)方便。
言歸正傳,下面我一個(gè)一個(gè)的列出來C 使用過程中常見的坑:
無符號(hào)整數(shù)的錯(cuò)誤使用
for?(unsigned?int?i?=?10;?i?>=?0;?--i)?{?...?}上面這段代碼會(huì)發(fā)生什么? 會(huì)死循環(huán),這里要注意下無符號(hào)整數(shù)的使用。
容器的size()返回類型是無符號(hào)整數(shù)
std::vector? vec;vec.push_back(1); for?(auto?idx?=?vec.size();?idx?>=?0;?idx--)?{cout?<<?"=====?\n"; }這段代碼依舊會(huì)出現(xiàn)死循環(huán),原因參考上一條。
STL遍歷刪除時(shí)注意迭代器失效問題
void erase(std::vector<int> &vec, int a) { ? ?for (auto iter = vec.begin(); iter != vec.end();) { // 這個(gè)正確 ? ? ? ?if (*iter == a) { ? ? ? ? ? ?iter = vec.erase(iter); ? ? ? ?} else { ? ? ? ? ? ? iter; ? ? ? ?} ? ?}for (auto iter = vec.begin(); iter != vec.end(); iter) { ?// error ? ? ? ?if (*iter == a) { ? ? ? ? ? ?vec.erase(iter); // error ? ? ? ?} ? ?}}std::list排序使用自己的成員方法
一般的容器排序都使用std::sort(),但是list特殊。
int?main()?{std::list?list{1,?2,?3,?2};????list.sort();????//?std::sort(list.begin(),?list.end());????for?(auto?i?:?list)?{std::cout?<<?i?<<?"?";????}????std::cout?<<?"\n";????return?0; }注釋用/**/,而不是//
注釋用/**/,可能會(huì)出問題。原因:utf-8和ANSC(GB2312)編碼混亂后,中文注釋就亂碼了,亂碼中藏著 */,匹配錯(cuò)了,導(dǎo)致IDE實(shí)際注釋的部分并非肉眼所見,定位極其困難,常見于Windows中。
不要返回局部變量的指針或引用
char*?func()?{char?a[3]?=?{'a',?'b',?'c'};????return?a; }棧內(nèi)存容易被污染。
浮點(diǎn)數(shù)判斷是否相等問題
float?f; if?(f?==?0.2)?{}?//?錯(cuò)誤用法 if?(abs(f?-?0.2)?<?0.00001)?{}?//?正確用法vector clear和swap問題
清空某個(gè)vector,可以使用swap而不是其clear方法,這樣可以更早的釋放vector內(nèi)部內(nèi)存。
vector?vec; vector().swap(vec); vec.clear();vector問題
盡量不要在vector中存放bool類型,vector為了做優(yōu)化,它的內(nèi)部存放的其實(shí)不是bool。
條件變量
條件變量的使用有兩大問題:信號(hào)丟失和虛假喚醒,相當(dāng)重要。
類型轉(zhuǎn)換
在C 中盡量使用C 風(fēng)格的四種類型轉(zhuǎn)換,而不要使用C語言風(fēng)格的強(qiáng)制類型轉(zhuǎn)換。
std::thread的使用
一定要記得join或這detach,否則會(huì)crash。
void?func()?{} int?main()?{std::thread?t(func);????if?(t.joinable())?{t.join();?//?或者t.detach();?????}????return?0; }enum使用
盡量使用enum class替代enum,enum class 是帶有作用域的枚舉類型。
空指針使用nullptr而不是NULL
void func(char*) { ? ?cout << "char*";}void func(int) { ? ?cout << "int";} int main() { ? ? func(NULL); // 編譯失敗 error: call of overloaded ‘func(NULL)’ is ambiguous ? ?func(nullptr); // char* ? ?return 0;}std::remove的使用
這個(gè)remove其實(shí)并沒有真正的刪除元素,需要和erase配合使用,跑一下這段代碼就知道啦。
bool isOdd(int i) { return i & 1; } void print(const std::vector<int>& vec) { ? ?for (const auto& i : vec) { ? ? ? ?std::cout << i << ' '; ? ?} ? ?std::cout << std::endl;} int main() { ? ?std::vector<int> v = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; ? ?print(v);std::remove(v.begin(), v.end(), 5); ?// error ? ?print(v);v.erase(std::remove(v.begin(), v.end(), 5), v.end()); ? ?print(v);v.erase(std::remove_if(v.begin(), v.end(), isOdd), v.end()); ? ?print(v);}全局變量初始化問題
不同文件中的全局變量初始化順序不固定,全局變量盡量不要互相依賴,否則由于初始化順序不固定的問題,可能會(huì)導(dǎo)致bug產(chǎn)生。
END
聲明:
本文于網(wǎng)絡(luò)整理,版權(quán)歸原作者所有,如來源信息有誤或侵犯權(quán)益,請(qǐng)聯(lián)系我們刪除或授權(quán)事宜。
總結(jié)
以上是生活随笔為你收集整理的C 的16个大坑,你能躲过几个?的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: iPhone14手机一次整理多个桌面图标
- 下一篇: iOS / iPadOS 16.5 Be