在线观看www成人影院-在线观看www日本免费网站-在线观看www视频-在线观看操-欧美18在线-欧美1级

0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會員中心
創(chuàng)作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

C++項目常見的命名規(guī)范

lhl545545 ? 來源:C語言與CPP編程 ? 作者:C語言與CPP編程 ? 2022-09-27 09:12 ? 次閱讀

本系列是開源書C++ Best Practises[1]的中文版,全書從工具、代碼風格、安全性、可維護性、可移植性、多線程、性能、正確性等角度全面介紹了現代C++項目的最佳實踐。本文是該系列的第二篇。

C++最佳實踐:

1. 工具

2. 代碼風格(本文)

3.安全性

4.可維護性

5.可移植性及多線程

6.性能

7.正確性和腳本

代碼風格

代碼風格最重要的是一致性,其次是遵循C++程序員習慣的閱讀風格。

C++允許任意長度的標識符名稱,因此在命名時沒必要非要保持簡潔,建議使用描述性名稱,并在風格上保持一致。

CamelCase(駝峰命名法)

snake_case(蛇形命名法)

這兩種是很常見的命名規(guī)范,snake_case的優(yōu)點是,在需要的時候可以適配拼寫檢查器。

建立代碼風格指南

無論建立什么樣的代碼風格指南,一定要實現指定期望風格的.clang-format文件。雖然這對命名沒有幫助,但對于開源項目來說,保持一致的風格尤為重要。

許多IDE、編輯器都支持內置的clang-format,或者可以很方便的通過加載項安裝。

VSCode: Microsoft C/C++ extension for VS Code[2]

CLion: ClangFormat as alternative formatter?

VisualStudio: ClangFormat[3]

Resharper++: Using Clang-Format[4]

Vim

Format your C family code[5]

vim-autoformat[6]

XCode: ClangFormat-Xcode[7]

通用C++命名約定

類以大寫字母開頭: MyClass。

函數和變量以小寫字母開頭: myMethod。

常量全部大寫: const double PI=3.14159265358979323。

C++標準庫(以及其他著名C++庫,如Boost[8])使用以下指導原則:

宏使用大寫和下劃線: INT_MAX。

模板參數名使用駝峰命名法: InputIterator。

所有其他名稱都使用蛇形命名法: unordered_map。

區(qū)分私有對象數據

使用m_前綴命名私有數據,以區(qū)別于公共數據,m_代表“member(成員)”數據。

區(qū)分函數參數

最重要的是保持代碼庫的一致性,這是一種有助于保持一致性的方式。

使用t_前綴命名函數參數,t_可以被認為是“the”,但其可以表示任意含義,關鍵是要將函數參數與作用域內的其他變量區(qū)分開來,同時遵循一致的命名策略。

可以為團隊選擇任何前綴或后綴,下面是一個例子,提出了一個有爭議的建議,相關討論見issue #11[9]。

structSize
{
intwidth;
intheight;

Size(intt_width,intt_height):width(t_width),height(t_height){}
};

//Thisversionmightmakesenseforthreadsafetyorsomething,
//butmoretothepoint,sometimesweneedtohidedata,sometimeswedon't.
classPrivateSize
{
public:
intwidth()const{returnm_width;}
intheight()const{returnm_height;}
PrivateSize(intt_width,intt_height):m_width(t_width),m_height(t_height){}

private:
intm_width;
intm_height;
};

不要用下劃線(_)作為名字的開頭

_ 開頭的名字有可能與編譯器或標準庫的保留名發(fā)生沖突: What are the rules about using an underscore in a C++ identifier?[10]

良好代碼風格示例

classMyClass
{
public:
MyClass(intt_data)
:m_data(t_data)
{
}

intgetData()const
{
returnm_data;
}

private:
intm_data;
};

使Out-of-Source-Directory構建

確保構建生成的文件存放在與源文件夾分離的輸出文件夾中。

使用nullptr

C++11引入了nullptr表示空指針,應該用來代替0或NULL來指示空指針。

注釋

注釋塊應該使用//,而不是/* */,使用//可以更容易的在調試時注釋掉代碼塊。

//thisfunctiondoessomething
intmyFunc()
{
}

要在調試期間注釋掉這個函數塊,可以這樣做:

/*
//thisfunctiondoessomething
intmyFunc()
{
}
*/

如果函數頭注釋使用/* */,這么做就會有沖突。

永遠不要在頭文件中使用using namespace

這會導致正在using的命名空間被強行拉入到包含頭文件的所有文件的命名空間中,從而造成命名空間污染,并可能在導致名稱沖突。在實現文件中using命名空間就足夠了。

Include保護符

頭文件必須包含名稱清晰的include保護符,從而避免同一頭文件被多次include的問題,并防止與其他項目的頭文件發(fā)生沖突。

#ifndefMYPROJECT_MYCLASS_HPP
#defineMYPROJECT_MYCLASS_HPP

namespaceMyProject{
classMyClass{
};
}

#endif

此外還可以考慮使用#pragma once指令,這是許多編譯器的準標準,內容簡短,意圖明確。

代碼塊必須包含{}

省略{}可能會導致代碼語義錯誤。

//BadIdea
//Thiscompilesanddoeswhatyouwant,butcanleadtoconfusing
//errorsifmodificationaremadeinthefutureandcloseattention
//isnotpaid.
for(inti=0;i

保持每行代碼長度合理

//BadIdea
//hardtofollow
if(x&&y&&myFunctionThatReturnsBool()&&caseNumber3&&(15>12||212||2

許多項目和編碼標準都對此制定了軟規(guī)則,即每行字符應該少于80或100個,這樣的代碼通常更容易閱讀,此外還可以把兩個文件并排顯示在一個屏幕上,不用小字體也能看到全部代碼。

使用""表示include本地文件

...<>表示include系統文件[11]。

//BadIdea.Requiresextra-Idirectivestothecompiler
//andgoesagainststandards.
#include
#include

//WorseIdea
//Requirespotentiallyevenmorespecific-Idirectivesand
//makescodemoredifficulttopackageanddistribute.
#include
#include


//GoodIdea
//Requiresnoextraparamsandnotifiestheuserthatthefile
//isalocalfile.
#include
#include"MyHeader.hpp"

初始化成員變量

...使用成員初始化列表。

對于POD類型,初始化列表的性能與手動初始化相同,但對于其他類型,有明顯的性能提升,見下文。

//BadIdea
classMyClass
{
public:
MyClass(intt_value)
{
m_value=t_value;
}

private:
intm_value;
};

//BadIdea
//Thisleadstoanadditionalconstructorcallform_myOtherClass
//beforetheassignment.
classMyClass
{
public:
MyClass(MyOtherClasst_myOtherClass)
{
m_myOtherClass=t_myOtherClass;
}

private:
MyOtherClassm_myOtherClass;
};

//GoodIdea
//Thereisnoperformancegainherebutthecodeiscleaner.
classMyClass
{
public:
MyClass(intt_value)
:m_value(t_value)
{
}

private:
intm_value;
};

//GoodIdea
//Thedefaultconstructorform_myOtherClassisnevercalledhere,so
//thereisaperformancegainifMyOtherClassisnotis_trivially_default_constructible.
classMyClass
{
public:
MyClass(MyOtherClasst_myOtherClass)
:m_myOtherClass(t_myOtherClass)
{
}

private:
MyOtherClassm_myOtherClass;
};

在C++11中,可以為每個成員初始化默認值(使用=或使用{})。

使用=設置默認值

//...//
private:
intm_value=0;//allowed
unsignedm_value_2=-1;//narrowingfromsignedtounsignedallowed
//...//

這樣可以確保不會出現構造函數“忘記”初始化成員對象的情況。

用大括號初始化默認值

用大括號初始化不允許在編譯時截斷數據長度。

//BestIdea

//...//
private:
intm_value{0};//allowed
unsignedm_value_2{-1};//narrowingfromsignedtounsignednotallowed,leadstoacompiletimeerror
//...//

除非有明確的理由,否則優(yōu)先使用{}初始化,而不是=。

忘記初始化成員會導致未定義行為錯誤,而這些錯誤通常很難發(fā)現。

如果成員變量在初始化后不會更改,則將其標記為const。

classMyClass
{
public:
MyClass(intt_value)
:m_value{t_value}
{
}

private:
constintm_value{0};
};

由于不能給const成員變量賦值,拷貝賦值操作可能對這樣的類沒有意義。

總是使用命名空間

幾乎沒有理由需要全局命名空間中聲明標識符。相反,函數和類應該存在于適當命名的命名空間中,或者存在于命名空間里的類中。放在全局命名空間中的標識符有可能與來自其他庫(主要是沒有命名空間的C庫)的標識符發(fā)生沖突。

為標準庫特性使用正確的整數類型

標準庫通常使用std::size_t來處理與尺寸相關的內容,size_t的大小由實現定義。

一般來說,使用auto可以避免大部分問題。

請確保使用正確的整數類型,并與C++標準庫保持一致,否則有可能在當前使用的平臺上不會發(fā)出警告,但如果切換到其他平臺,可能會發(fā)出警告。

注意,在對無符號數執(zhí)行某些操作時,可能會導致整數下溢。例如:

std::vectorv1{2,3,4,5,6,7,8,9};
std::vectorv2{9,8,7,6,5,4,3,2,1};
constautos1=v1.size();
constautos2=v2.size();
constautodiff=s1-s2;//diffunderflowstoaverylargenumber

使用.hpp和.cpp作為文件擴展名

歸根結底,這是個人喜好問題,但是.hpp和.cpp已被各種編輯器和工具廣泛認可。因此,這是一個務實的選擇。具體來說,Visual Studio只自動識別.cpp和.cxx為C++文件,而Vim不一定會把.cc識別為C++文件。

某個特別大的項目(OpenStudio[12])使用.hpp和.cpp表示用戶生成的文件,而使用.hxx和.cxx表示工具生成的文件。兩者都能被很好的識別,并且區(qū)分開來有很大的幫助。

不要混用tab和空格

某些編輯器喜歡在默認情況下使用tab和空格的混合縮進,這使得沒有使用完全相同的tab縮進設置的人很難閱讀代碼。請配置好編輯器,確保不會發(fā)生這種情況。

不要將有副作用的代碼放在assert()中

assert(registerSomeThing());//makesurethatregisterSomeThing()returnstrue

上述代碼在debug模式下構建時可以成功運行,但在進行release構建時會被編譯器刪除,從而造成debug和release構建的行為不一致,原因在于assert()是一個宏,它在release模式下展開為空。

不要害怕模板

模板可以幫助我們堅持DRY原則[13]。由于宏有不遵守命名空間等問題,因此能用模板的地方就不要用宏。

明智的使用操作符重載

運算符重載是為了支持表達性語法。比如讓兩個大數相加看起來像a + b,而不是a.add(b)。另一個常見的例子是std::string,通常使用string1 + string2連接兩個字符串。

但是,使用過多或錯誤的操作符重載很容易寫出可讀性不強的表達式。在重載操作符時,要遵循stackoverflow文章[14]中描述的三條基本規(guī)則。

具體來說,記住以下幾點:

處理資源時必須重載operator=(),參見下面Rule of Zero章節(jié)。

對于所有其他操作符,通常只有在需要在上下文中使用時才重載。典型的場景是用+連接事物,負號可以被認為是“真”或“假”的表達式,等等。

一定要注意操作符優(yōu)先級[15],盡量避免不直觀的結構。

除非實現數字類型或遵循特定域中可識別的語法,否則不要重載~或%這樣的外部操作符。

永遠不要重載```operator,()```[16](逗號操作符)。

處理流時使用非成員函數operator>>()和operator<<()。例如,可以重載operator<<(std::ostream &, MyClass const &),從而允許將類“寫入”到一個流中,例如std::cout或std::fstream或std::stringstream,后者通常用于創(chuàng)建值的字符串表示。

這篇文章描述了更多需要重載的常見操作符: What are the basic rules and idioms for operator overloading?[17]。

更多關于自定義操作符實現細節(jié)的技巧可以參考: C++ Operator Overloading Guidelines[18]。

避免隱式轉換

單參數構造函數

可以在編譯時應用單參數構造函數在類型之間自動轉換,比如像std::string(const char *),這樣的轉換很方便,但通常應該避免,因為可能會增加額外的運行時開銷。

相反,可以將單參數構造函數標記為explicit,從而要求顯式調用。

轉換操作符

與單參數構造函數類似,編譯器可以調用轉換操作符,同樣也會引入額外開銷,也應該被標記為explicit。

//badidea
structS{
operatorint(){
return2;
}
};

//goodidea
structS{
explicitoperatorint(){
return2;
}
};

考慮Rule of Zero

Rule of Zero規(guī)定,除非所構造的類具有某種新的所有權形式,否則不提供編譯器可以提供的任何函數(拷貝構造函數、拷貝賦值操作符、移動構造函數、移動賦值操作符、析構函數)。

目標是讓編譯器提供在添加更多成員變量時自動維護的最佳版本。

這篇文章介紹了這一原則的背景,并解釋了幾乎可以覆蓋所有情況的實現技術: C++'s Rule of Zero[19]。

審核編輯:彭靜
聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發(fā)燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規(guī)問題,請聯系本站處理。 舉報投訴
  • 開源
    +關注

    關注

    3

    文章

    3624

    瀏覽量

    43532
  • C++
    C++
    +關注

    關注

    22

    文章

    2117

    瀏覽量

    74828
  • 代碼
    +關注

    關注

    30

    文章

    4891

    瀏覽量

    70307
  • 編輯器
    +關注

    關注

    1

    文章

    818

    瀏覽量

    31815

原文標題:C++最佳實踐 | 2. 代碼風格

文章出處:【微信號:C語言與CPP編程,微信公眾號:C語言與CPP編程】歡迎添加關注!文章轉載請注明出處。

收藏 人收藏

    評論

    相關推薦
    熱點推薦

    現代C++項目的最佳實踐

    本系列是開源書C++ Best Practises[1]的中文版,全書從工具、代碼風格、安全性、可維護性、可移植性、多線程、性能、正確性等角度全面介紹了現代C++項目的最佳實踐。本文是該系列的第三篇。
    發(fā)表于 09-29 11:32 ?1456次閱讀

    焊盤命名規(guī)范

    焊盤命名規(guī)范 通常我們的焊盤分為通過孔(THP)焊盤和表貼(SMD)焊盤兩種形式。但這兩種形式當中,又有多種形狀。所以我們要有一個統一的命名規(guī)范,以方便以后調用。一、THP焊盤
    發(fā)表于 12-31 17:27

    C語言常見命名規(guī)則

    C語言常見命名規(guī)則
    發(fā)表于 08-17 14:44

    關于Android命名規(guī)范

    ”。接手別人的項目,如果對方代碼規(guī)范,是好事,可以學學人家如何寫的,如果代碼隨意,那就蛋疼了,像我這種強迫癥患者,一刻都不能忍,分分鐘就想重構!下面列舉幾個我接盤項目遺留的坑:包名包名全部小寫編寫,連續(xù)
    發(fā)表于 10-15 00:11

    關于Android命名規(guī)范

    ”。接手別人的項目,如果對方代碼規(guī)范,是好事,可以學學人家如何寫的,如果代碼隨意,那就蛋疼了,像我這種強迫癥患者,一刻都不能忍,分分鐘就想重構!下面列舉幾個我接盤項目遺留的坑:包名 包名全部小寫編寫,連續(xù)
    發(fā)表于 06-21 09:35

    嵌入式開發(fā)程序的架構和命名規(guī)范

    c/c++程序風格約定文/Mike往往我們做單片機程序開發(fā)的時候,很少去注意程序的架構和命名規(guī)范,然而只要是涉及到代碼開發(fā),這都是不可回避的問題,很多小公司做嵌入式的開發(fā),在技術上沒有
    發(fā)表于 11-05 08:22

    使用C++項目的正確方法是什么?

    在 STM32CubeIDE 中,我創(chuàng)建了一個 C++ 項目。但是 `main.c` 仍然以 .c 擴展名生成,并使用 C 編譯器編譯。這就
    發(fā)表于 02-07 08:34

    C++命名空間的幾大用法

    的: 命名空間定義了新的作用域。它們提供了一種避免名稱沖突的方法。 c++ 中的命名空間通常用于避免命名沖突。盡管命名空間在最近的
    發(fā)表于 09-28 18:31 ?0次下載

    CC++的編程規(guī)范資料免費下載

    本文檔的主要內容詳細介紹的是CC++的編程規(guī)范資料免費下載包括了:1. 文件結構,2. 程序版式,3 命名規(guī)則,4. 表達式和基本語句,5. 常量,6. 函數設計,7 重載和內聯,8
    發(fā)表于 04-08 08:00 ?5次下載
    <b class='flag-5'>C</b>和<b class='flag-5'>C++</b>的編程<b class='flag-5'>規(guī)范</b>資料免費下載

    C++語言編碼規(guī)范詳細說明

    本文檔的主要內容詳細介紹的是C++語言編碼規(guī)范詳細說明。
    發(fā)表于 01-07 16:19 ?18次下載
    <b class='flag-5'>C++</b>語言編碼<b class='flag-5'>規(guī)范</b>詳細說明

    一文了解C++命名空間

    C++中,變量、函數和類都是大量存在的,這些變量、函數和類的名稱將都存在于全局命名空間中,會導致很多沖突, 使用命名空間的目的是對標識符的名稱進行本地化,以避免命名沖突或名字污染,N
    的頭像 發(fā)表于 06-29 14:48 ?2490次閱讀
    一文了解<b class='flag-5'>C++</b>的<b class='flag-5'>命名</b>空間

    關于軟件、硬件版本號命名常見規(guī)范

    不知道大家寫程序、畫板子時,版本號是怎么命名的? ? 最常見的就是V1.0.0這種簡單的形式命名,復雜一點就是帶有日期、后綴等版本信息。 ? 當然,版本號命名
    的頭像 發(fā)表于 12-31 10:04 ?5373次閱讀

    C++語言里有哪些比較常見的坑?

    ? 前段時間給部門做了個C++專題的分享,主要分享了C++語言里一些常見的坑,在這里也分享給大家。 ? 首先說下C++C語言有什么區(qū)別?分
    的頭像 發(fā)表于 05-20 11:38 ?2313次閱讀

    C++常見設計模式解析與實現

    C++常見設計模式解析與實現說明。
    發(fā)表于 06-01 15:44 ?11次下載

    c++知識要點

    第一章 開始 1.1 編寫一個簡單的C++程序 int main() { return 0; } 每個C++程序都包含一個或多個函數,其中一個必須命名為main.
    發(fā)表于 06-20 09:45 ?0次下載
    主站蜘蛛池模板: 32pao强力打造免费高速高清 | 一区二区三区高清不卡 | 激情六月网 | 色就是色欧美色图 | 天天上天天干 | 日日噜夜夜噜 | 亚洲国产成人久久午夜 | 狠狠色丁香久久婷婷 | 国产精品视频一区二区三区 | 一级片aaaaaa | 久久亚洲精选 | 欧美亚洲视频一区 | 美女视频黄a | 日本女人啪啪 | 人成网站在线观看 | 国产综合视频在线 | 亚洲综合在线最大成人 | 天堂网在线www资源网 | 男人天堂网在线观看 | 妖精视频一区二区三区 | 九九国产精品 | 成年人三级视频 | 亚洲成人午夜影院 | 午夜视频一区二区 | 天天干精品| 免费亚洲视频在线观看 | 午夜三级网 | 在线免费看影视网站 | 国产成人一区二区在线不卡 | 天堂视频网 | 一级特一级特色生活片 | 好爽好大www视频在线播放 | 色网视频| 婷婷综合五月中文字幕欧美 | 一级片在线观看视频 | 黄色免费网站在线 | l欧美18一19sex性 | 种子天堂bt磁力在线资源 | 狠狠色噜噜狠狠狠狠米奇777 | 国产情侣出租屋露脸实拍 | 一本到午夜92版免费福利 |