C++小Tips--持續update~

1. 動態空間分配失敗的判斷
可以調用set_new_handler,它是聲明於<new>的一個標準程序庫函數,它的參數是個new_handler指針,指向operator new無法分配足夠內存時該被調用的函數,返回值也是個指針,指向它被調用前正在執行的那個new-handler函數。參考《Effective C++》中文第三版,P240-241

#include <iostream>
#include <new>
using namespace std;
//當operator new無法分配足夠內存時被調用的函數
void noMemory()
{
cout<<"no adequate memory left"<<endl;
//退出程序,若無abort則直到成功分配內存爲止
abort();
}
int main()
{
set_new_handler(noMemory);
int *nums = new int[10000000000];
}

2. 動態數組通過傳參獲得而非直接返回
int *turnArray()

{
    int *nums;
    //code here...
    return nums;
}
若以這種返回方式獲得數組容易出現無法讀出等詭異問題,改爲引用方式獲取比較保險
void turnArray(int *&nums)
{
    //code here...
}

3. 繼承
對於在多個類中都會被使用的參數或調用的函數函數可將它們寫在一個基類中,其它類繼承這個基類
class basico
{
    public:
    int n;
    bool inputNums(int *&);
    void outputNums(int *,int);
};
class abcd:public basico
{
    //......
};
class efgh:public basico
{
    //......
};
abcd和efgh的成員函數中都可以使用參數n和調用成員函數inputNums()/outputNums()

4. 可將返回void的函數改爲返回bool
便於之後的調試和異常處理。有時候一個函數可能執行不成功,這時需要返回一個錯誤信息終止程序執行,在調用該函數的地方,若返回true則繼續,若爲false則輸出錯誤信息並終止。對於連續執行多個函數的程序來說,便於出錯定位。

5. 非引用形參與引用形參
非引用形參只是對參數局部副本的操作,函數結束之後對實參沒有任何影響;引用形參與相應的實參關聯,函數結束之後對引用形參的操作將體現在實參上。

void swapA(int i,int j)
{
int temp;
temp = i;
i = j;
j = temp;
}
void swapB(int &i,int &j)
{
int temp;
temp = i;
i = j;
j = temp;
}
int main()
{
int i = 10,j = 20;
swapA(i,j);
cout<<"A: "<<i<<" "<<j<<endl;
swapB(i,j);
cout<<"B: "<<i<<" "<<j<<endl;
return 0;
}
輸出結果爲:
A: 10 20
B: 20 10

6. error: stray ‘\357’ in program
若編譯時提示類似錯誤,則是因爲代碼中有中文格式的字符,請仔細檢查之。

7. 生成小於1.0的隨機浮點數並取小數點後兩位

double k;
srand((unsigned)time(NULL));  //需要#include<time.h>
for(int i = 0;i < 5;i++)
{
	k = (1.0*rand())/RAND_MAX;
	cout<<k<<"-";
	//需要 #include<iomanip>
	//cout<<setprecision(2)<<k<<endl;  //輸出時取兩位小數(結果被四捨五入)
	k = (double)(int)(k*100)/100;   //直接截取k的小數點後兩位,不四捨五入
	cout<<k<<endl;
}

以上代碼輸出結果:
0.870822-0.87
0.630963-0.63
0.316664-0.31
0.151696-0.15
0.401322-0.4

 8. string類型轉爲int類型

string str;
int num = atoi(str.c_str());

9. 箭頭操作符(->)和點操作符(.) (轉)

一個左邊是指針.
一個左邊是實體
如果p是指針, p->function();
如果p是對象, p.function();
記住(->)必須是指針,(.)左邊必須是對象或者結構體,一般是類對象
比如:容器的迭代器iter
iter->function() = (*iter).function();
例如vector<pair<string,int> >容器Vec和迭代器vit
取出容器中第2個元素的操作可以有兩種:
(1) Vec[1].first; Vec[1].second;
(2) vit = Vec.begin()+1; vit->first; vit->second;

10. 釋放動態空間時報錯:*** glibc detected ***  free(): invalid next size (fast)

int **buck = (int **)malloc(sizeof(int *)*10);
for(i = 0;i < 10;i++)
{
	set_new_handler(noMemory);
	//要+1否則在釋放buck[i]時會報錯【free(): invalid next size (fast)】
	buck[i] = (int *)malloc(sizeof(int)*temp[i]+1);
}
//釋放空間
for(i = 0;i < 10;i++)
	free(buck[i]);
free(buck);

一種方法是在爲buck[i]分配空間時加1,否則釋放buck[i]空間時會報出如上錯誤,網上有說是由於內存越界引起的(是否是由於temp[i]==0時並沒有爲buck[i]分配內存,導致地址無效或空間大小無效,而釋放空間時仍然對其進行釋放引起的?)
在分配空間時+1浪費內存,另一種方法在釋放空間時進行NULL判斷,若不爲NULL才釋放,代碼如下:

int **buck = (int **)malloc(sizeof(int *)*10);
for(i = 0;i < 10;i++)
{
	set_new_handler(noMemory);
	buck[i] = (int *)malloc(sizeof(int)*temp[i]);
}
//釋放空間
for(i = 0;i < 10;i++)
{
	if(buck[i] == NULL)
		continue;
	else
		free(buck[i]);
}
free(buck);

malloc工作機制:malloc函數的實質體現在,它有一個將可用的內存塊連接爲一個長長的列表的所謂空閒鏈表;調用malloc函數時,它沿鏈表尋找一個大到足以滿足用戶請求所需要的內存塊;然後將分配給用戶的那塊內存傳給用戶,並將剩下的那塊返回到鏈表上;釋放free時,將用戶釋放的內存塊連接到空閒鏈表上。最後空閒鏈可能會被切成很多小的內存片段,這時空閒鏈上可能沒有可以滿足用戶申請需要的那麼大的片段,此時malloc請求延時,開始在鏈表上檢查內存片段並進行調整,將相鄰的小片段合併成大的內存塊。

11. printf()的返回值
printf()返回一個int類型的值,它的大小爲打印的字符個數。例如:
int i = 43;
printf("%d\n",printf("%d",printf("%d",i)));
打印結果爲:4321
cout<<printf("%s","漢字")<<endl;
打印結果爲:漢字6

12. && 運算符
當左右兩邊的數均爲非0時結果爲1,當有一個爲0時結果爲0。以下代碼當x爲0或1時,打印結果爲1,其它情況打印結果爲0.
printf("%d\n",x == (1 && x));

13. 對map按value值排序
當存儲時需要以string爲標識方便查找並且保證不重複插入,而又希望按int值的排序順序輸出,此時可以用如下方法對map按value值排序。

#include <math.h>
#include <algorithm>
typedef pair<string, int> PAIR;  
int cmp(const PAIR& x, const PAIR& y)  
{  
    return x.second > y.second;  
}
vector<PAIR> idVec;
map<string,int> tycID;
for (map<string,int>::iterator mapIt = tycID.begin();mapIt != tycID.end();mapIt++)
{
	idVec.push_back(make_pair(mapIt->first,mapIt->second));
}
sort(idVec.begin(),idVec.end(),cmp);
for (vector<PAIR>::iterator idIt = idVec.begin();idIt != idVec.end();idIt++)
{
	cout<<idIt->first<<" "<<idIt->second<<endl;
}

14. 字符串類型轉換

char conv[WORDBUF];
string str = "have";
char *word = (char *)str.c_str();
sprintf(conv,"%s",word);
用此方法將string類型轉換爲char數組類型。

15. 逐個獲取以空格分隔的string中的詞語

#include <sstream>

string word;
string str = "一定 要 先 仔細 閱讀 中獎 規則 和 購買 須知";
stringstream stream(str);
while(stream>>word)
	cout<<word<<endl;

16.將int轉化爲string類型

 int i=1011;
 string str;
 ostringstream stream;
 stream<<i;
str=stream.str();
 cout<<str<<endl;


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章