C++编程原则2 tcy
生活随笔
收集整理的這篇文章主要介紹了
C++编程原则2 tcy
小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
8)函數(shù)編寫原則
9)避免代碼重復(fù)
10)復(fù)制后交換
11)不要在使用C語言的風(fēng)格
12)刪除-擦除技術(shù)
13)if...else優(yōu)化技術(shù)參考本人博文
14)少用循環(huán)
1.函數(shù)編寫原則?
1.1.基本原則:1)只做一件事情;讓函數(shù)盡可能小12-15行2)盡量使用內(nèi)聯(lián)函數(shù);一般可以忽略函數(shù)的調(diào)用開銷3)通過引用傳遞結(jié)構(gòu)體而不是傳值;小心使用表查找函數(shù);對(duì)GPU編程優(yōu)先使用表查找 1.2.函數(shù)命名通常是動(dòng)詞狀態(tài)函數(shù)is...,has...;使用容易理解名字 1.3.函數(shù)參數(shù)1)減少函數(shù)參數(shù)個(gè)數(shù),應(yīng)小于3個(gè),類中可無參數(shù)舊函數(shù)參數(shù)太多重新包裝;用struct合并一些參數(shù)2)避免使用標(biāo)志參數(shù)void foo(){ if(readMode) {} else {}}//應(yīng)分成2個(gè)單獨(dú)良好命名的函數(shù)3)盡可能使用const防止傳遞給函數(shù)的參數(shù)被修改const long double PI=3.1415926;int foo(Car const*car); //靜態(tài)指針變量-指針指向內(nèi)容不能被修改 等價(jià)const Char* carvoid foo(Car* const car); //指針常量,可修改car,但不能修改指針int foo(Car const* const car); //都不能修改void view(const string& message); //靜態(tài)字符串引用,不許修改strvoid view(string const& message); //等同上面 注:const都會(huì)修飾他左邊的內(nèi)容,如左邊沒內(nèi)容就修飾右邊 1.4.函數(shù)返回值1)避免使用輸出參數(shù)-不惜一切代價(jià)也要避免使用輸出參數(shù)2)多輸出使用std::pair,std::tuple(僅在特殊情況使用)通常用struct類如果你還必須區(qū)分成功失敗,可用所謂的特例模式實(shí)例:多個(gè)輸出值using pairType = pair<int, string>;using tupleType = tuple<int, string, string>;struct resultType{int i;string s;}; pairType foo(){ return pair<int, string> { 1,"Tom" }; }tupleType bar() { return make_tuple( 2, "Tom", "Bob"); }//tupleType{}resultType func() { return resultType{ 3,"Jim" }; } int main() {int i; string s; pairType p=foo();std::tie(i, s) = p;assert(i==p.first);assert(s==p.second);tupleType t = bar();std::tie(i, s, ignore) = t;assert(i==std::get<0>(t));assert(s==std::get<1>(t));resultType r = func();cout<<r.i<<r.s<<endl; } 1.5.指針參數(shù)或返回值 1)說明:a)不要傳遞或返回nullptr,把要做什么轉(zhuǎn)移給調(diào)用者會(huì)出現(xiàn)很多選擇語句b)如函數(shù)返回常規(guī)指針確保指針始終指向有效地址,為nullptr則拋出異常. 2)避免指針策略:a)首選在棧上而不是在堆上構(gòu)造對(duì)象;move擺脫大量常規(guī)指針int foo(){int tmp=1;return tmp;} //在棧上vector<int> foo(){vector<int> vec{2};return vec;}//原因所謂move,所有容器都支持 b)在函數(shù)參數(shù)用const引用代替指針void func(Type* p);void func(const Type& p); c)如不可避免使用處理指向資源的指針請(qǐng)用智能指針如必須在堆上分配資源應(yīng)利用RAII(資源申請(qǐng)即初始化)意味這你使用智能指針 d)第三方庫API返回原始指針有依賴問題,通常不在我們的控制范圍可創(chuàng)建自定義智能指針來包裝常規(guī)指針,由API的allocator分配,deallocator需重新包裝 3)實(shí)例:訪問windows資源#include<windows.h>typedef void *HANDLE;const DWORD processId= 4711;HANDLE processHandle=OpenProcess(PROCESS_ALL_ACCESS,FALSE,processId);//檢索進(jìn)程句柄BOOL success=CloseHandle(processHandle);//關(guān)閉句柄< /FONT>//包裝:自定義刪除器deleterclass Win32HandleCloser{public:void operator()(HANDLE handle)const{ if(handle!=INVALID_HANDLE_VALUE) CloseHandle(handle);}}; using Win32SharedHandle=std::shared_ptr<HANDLE>;const DWORD processId= 4711;Win32SharedHanle processHandle{OpenProcess(PROCESS_ALL_ACCESS,FALSE,processId),Win32HandleClosedr());2.避免代碼重復(fù)?
1.1.說明:避免代碼重復(fù),傳統(tǒng)做法用const版本實(shí)現(xiàn)非const版本建議使用變?yōu)閏onst又變回來技術(shù)來避免代碼重復(fù)。 1.2.一般來說使用下面的模式:returnType Class::func(arguments){ return const_cast<returnType>(std::as_const(*this).func(arguments ));}//return const_cast<T&>(static_cast<const Array<T>&>(*this)[index]); 2.實(shí)例:template <typename T>T& Array<T>::operator[](size_t index){Array<T>& nonConstRef=*this;const Array<T>& constRef=as_const(nonConstRef);//轉(zhuǎn)變?yōu)閏onst引用const T& constResult= constRef[index]; //獲取const結(jié)果 return const_cast<T&>(constResult); //轉(zhuǎn)換到非const結(jié)果}3.復(fù)制后交換?
1.1.定義:任何函數(shù)都可拋出異常(除noexcept標(biāo)注函數(shù),析構(gòu)函數(shù))操作要么全部成功要么全部失敗,可使用的編程模式稱為復(fù)制后交換1.2.用途:如在修改中出現(xiàn)異常丟棄副本原對(duì)象不變;任何代碼都可運(yùn)用,但常用在成員函數(shù)中1.3.步驟:如修改一個(gè)或多個(gè)對(duì)象狀態(tài),任何步驟都可拋異常,應(yīng)采用下面簡單模式:1)創(chuàng)建對(duì)象的一個(gè)副本2)修改對(duì)象的副本而不是原對(duì)象3)如果修改成功則用副本替換或交換原對(duì)象1.4.說明:1)復(fù)制后交換依賴如下假設(shè):最后的交換步驟沒有拋出異常的風(fēng)險(xiǎn)2)swap()用來交換任何可復(fù)制數(shù)據(jù)類型的值或?qū)ο?lt;utility>類似template<typename T> void swap(T& one,T& other)noexcept{ T copy(one); one=other; other= copy;} 2.實(shí)例: 實(shí)例1:template<typename T>class Array{};template<typename T> //版本1Array<T>& Array<T>::operator=(const Array& rhs){if(this!= &rhs){Array<T> copy(rhs};swap(copy);}return *this;}template<typename T> //版本2:不在需要檢查自我賦值A(chǔ)rray<T>& Array<T>::operator=(const Array& rhs){swap(rhs);return *this;}在Array<>對(duì)象應(yīng)用這個(gè)模板函數(shù)效率不高,被交換對(duì)象的所有元素會(huì)被復(fù)制多次,而且在我們的賦值運(yùn)算符中不能用他來交換*this 和copy.(會(huì)調(diào)用賦值運(yùn)算符出現(xiàn)無限遞歸調(diào)用) 實(shí)例2:添加swap成員函數(shù):應(yīng)實(shí)現(xiàn)一特化版本,因?yàn)锳rray<>成員變量是私有,一個(gè)選項(xiàng)將swap()定義為友元函數(shù)方法2向Array<>添加一個(gè)額外的成員函數(shù)swap()(也是vecor<>采用方法) template<typename T>void Array<T>::swap(Array& other) noexcept{std::swap(elements,other.elements);//交換兩個(gè)指針std::swap(size,other.size);}//然后使用該成員函數(shù)版本實(shí)現(xiàn)傳統(tǒng)的非成員函數(shù)swap()template<typename T>void swap(Array<T>&one,Array<T>& other) noexcept{ one.swap(other);} //轉(zhuǎn)發(fā)到公共成員功能4.不要在使用C語言的風(fēng)格?
1.避免使用宏1)常量定義constexpr double pi=3.1415926;函數(shù)宏用函數(shù)替代;2)主要用在特殊目的如單元測試或日志框架 2.用C++類型轉(zhuǎn)換代替C風(fēng)格強(qiáng)制轉(zhuǎn)換 2.1.說明:1)修改設(shè)計(jì)避免在任何情況下進(jìn)行類型轉(zhuǎn)換;2)如無法避免用static_cast,用遠(yuǎn)不要使用C風(fēng)格轉(zhuǎn)換3)不要使用dynamic_cast<>這是一個(gè)糟糕的設(shè)計(jì)4)在任何情況下永遠(yuǎn)不要使用reinterpret_cast<>.轉(zhuǎn)換不安全不可移植和依賴于實(shí)現(xiàn)等標(biāo)標(biāo)志2.2.實(shí)例:double d{3.14};int i= (int)d;int i= static_cast<int>(d);?
3.字符串 3.1.用string和stream替代char*char name[]= "Tom"; //用下面替換string name{"Tom"}; //string name("Tom"); //字符數(shù)組通常在傳遞其首元素的指針才能使用char *p= name;void func(char* pointerToCharacterArray); //唯一使用C風(fēng)格的字符串是字符串常量:const char* const address="shanghai"; 3.2.避免用printf,sprintf,gets數(shù)字類型都可to_string()轉(zhuǎn)換為字符串轉(zhuǎn)換唯一的缺點(diǎn)是有時(shí)是不準(zhǔn)確的double d{1e-9};改進(jìn):#include<string>#include<sstream>#include<iomanip> string doubleToString(const long double x,const int precision){stringstream stream{};stream<<std::fixed<<std::setprecision(precision)<<x;return stream.str();} 4.數(shù)組 4.1.固定數(shù)組用標(biāo)準(zhǔn)庫std::array<Type,N>替代int arr[]={1,2,3};void foo(int *arr,size_t n){} #include<array>array<int,3> arr{1,2,3};void foo(const array<int,3>& arr){size_t n=arr.size();} 4.2.可變數(shù)組用std::vector替換1)遵守以下規(guī)則(1)fun()不應(yīng)訪問超出數(shù)組范圍的元素(2)向量中元素必須是連續(xù)的2)說明:你用&vi[0]和&*v.front()作為其內(nèi)部數(shù)組地址就會(huì)很安全3)實(shí)例: void func(const int arr[], size_t length ){}int main(){vector <int> vec;func(&vec[0], vec.size());//或者&*v.front()} 4.3.動(dòng)態(tài)多維數(shù)組和向量//手動(dòng)分配多維數(shù)組,非常容易出錯(cuò)int (*pArr)[5] = new int[2][3]; //需要括號(hào)pArr[0][0] = 10;pArr[0][1] = 11;pArr[0][2] = 12;pArr[1][0] = 20;pArr[1][1] = 21;pArr[1][2] = 22;for (auto i = 0; i < 2; ++i){for (auto j = 0; j < 3; ++j)cout << pArr[i][j] << ",";cout << endl;}delete [] pArr; //使用vector來模擬多維數(shù)組是一個(gè)更好的選擇:#include <vector>#include <iostream>using namespace std; int main(){vector <vector <int> > v;v.push_back(vector <int>());v.push_back(vector <int>());v[0].push_back(10);v[0].push_back(11);v[0].push_back(12);v[1].push_back(20);v[1].push_back(21);v[1].push_back(22);for (auto v1 : v){for (auto v2 : v1)cout << v2 << ",";cout << endl;}}?
5.替換C語言中指針int* add(int* p1,int* p2){static int result = *p1 + *p2;return &result;} using intPtrType = shared_ptr<int>; intPtrType add(intPtrType p1, intPtrType p2){ return std::make_shared<int>(*p1 + *p2);} int main() {//普通指針測試:int x = 1, y = 2;int *px = &x, *py = &y;cout << *add(px, py) << endl;//smart指針測試:intPtrType p1 = make_shared<int>(x);intPtrType p2 = make_shared<int>(y);intPtrType r = add(p1, p2);cout << *r << endl; }?刪除-擦除技術(shù)
1.1.提示:不應(yīng)手動(dòng)迭代順序容器的元素,而是用刪除-擦除技術(shù)使用remove(),或remove_if()算法來刪除容器中滿足特定條件的元素1.2.remove(),或remove_if()返回迭代器指向要?jiǎng)h除的第一個(gè)元素不會(huì)真正刪除元素,會(huì)將不應(yīng)該刪除的元素移到輸入范圍的前部,需要?jiǎng)h除的元素移到后部 2.實(shí)例: 實(shí)例1:普通迭代刪除:效率低void removeEvenNumbers(NumberContainer& vec){for (auto iter{ vec.begin() }; iter != vec.end(); ){iter = (*iter % 2 == 0) ? vec.erase(iter) : (iter + 1);}} 實(shí)例2:刪除-擦除技術(shù)#include <vector>#include <string_view>#include <iostream>#include <algorithm>using namespace std;std::vector<int> fillVector(size_t N); // Fill a vector with 1, 2, ..., Nvoid print(std::string_view message, const std::vector<int>& vec);void removeEvenNumbers(std::vector<int>& vec);int main(){const size_t n{ 6 };auto vec{ fillVector(n) };print("The original set of vec", vec);removeEvenNumbers(vec);print("The vec that were kept", vec);}std::vector<int> fillVector(size_t N) // Fill a vector with 1, 2, ..., N{std::vector<int> vec;for (int i{ 1 }; i <= N; ++i)vec.push_back(i);return vec;}void print(std::string_view message, const std::vector<int>& vec){std::cout << message << ": ";for (int number : vec) std::cout << number << ' ';std::cout << std::endl;}void removeEvenNumbers(std::vector<int>& vec){// remove all even vecauto vector_iter{ std::remove_if(begin(vec),end(vec), [](int number) { return number % 2 == 0; }) };cout << typeid(vector_iter).name() << endl;//std::_Vector_iterator// Erase all elements including and beyond vector_itervec.erase(vector_iter, end(vec)); //erase缺少第二個(gè)參數(shù)將僅僅刪除一個(gè)元素}?
?
?
?
?
?
?
?
?
?
?
總結(jié)
以上是生活随笔為你收集整理的C++编程原则2 tcy的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: matlab怎么把音频变成信号_如何使用
- 下一篇: s3c2440移植MQTT