小知識(shí)點(diǎn):
每個(gè)線程都必須有一個(gè)初始函數(shù)陋桂,新線程的執(zhí)行開(kāi)始于初始函數(shù)岁歉。對(duì)于第一段程序來(lái)說(shuō)术羔,它的初始函數(shù)是main,對(duì)于我們新創(chuàng)建的線程寞焙,可以在std::thread()對(duì)象的構(gòu)造函數(shù)中指定储狭。
在第二段程序里,程序由兩個(gè)線程組成:初始線程始于main捣郊,新線程始于hello辽狈。這里將新線程t的初始函數(shù)指定為hello。
新線程啟動(dòng)之后會(huì)與初始進(jìn)程一并運(yùn)行呛牲,初始線程可以等待或不等待新進(jìn)程的運(yùn)行結(jié)束——如果需要等待線程刮萌,則新線程實(shí)例需要使用join(),否則可以使用detach()。如果不等待新線程侈净,則初始線程自顧自地運(yùn)行到main()結(jié)束尊勿。
# include<iostream>
# include<thread>
using namespace std;
void hello()
{
cout<<"hello world"<<endl;
}
int main()
{
thread t (hello);
t.join();
}
iostream “流”就是一個(gè)字符序列僧凤,表達(dá)的是:隨著時(shí)間的推移畜侦,字符是順序生成或消耗的
std::endl的作用不僅僅是結(jié)束當(dāng)前行,也有刷新緩沖區(qū)的作用
應(yīng)該保證每次cout后都刷新流否則若程序崩潰躯保,輸出可能還殘留在緩沖區(qū)中旋膳,導(dǎo)致關(guān)于程序崩潰位置錯(cuò)誤的推斷
初始化不是賦值,初始化含義是創(chuàng)建變量時(shí)賦予其一個(gè)初始值途事,而賦值含義是把對(duì)象的當(dāng)前值擦除并用新值替代
盡量初始化每一個(gè)內(nèi)置類型的變量
初始化所有指針验懊,若有必要聲明空指針,則盡量int *p = nullptr; 而不使用老式的null
extern int i; //聲明i尸变,而非定義i
int j; //聲明并定義j义图,任何包含了顯示初始化的聲明即為定義
.#ifndef DECLARE_CLASS_H //防止多次包含同一頭文件,名字全部大寫(xiě)
.#define DECLARE_CLASS_H
...
.#endif
頭文件中不應(yīng)包含using聲明
如果表達(dá)式中已經(jīng)有了size()函數(shù)召烂,就不要在使用int了
這可以避免混用int和unsigned可能帶來(lái)的問(wèn)題碱工,例如:
auto len = line.size(); //len的類型是string::size_type 一個(gè)無(wú)符號(hào)的整型
也就是說(shuō)要避免無(wú)符號(hào)和有符號(hào)的數(shù)據(jù)在一起運(yùn)算
所有用于存放string類的size()函數(shù)返回的變量,都應(yīng)該是string::size_type類型的
對(duì)于C++來(lái)說(shuō),應(yīng)盡量使用不帶.h的頭文件怕篷,以減少不必要的麻煩
現(xiàn)代C++來(lái)說(shuō)历筝,盡量使用string、vector和迭代器廊谓,避免使用數(shù)組梳猪、指針和C風(fēng)格字符串
但凡是使用了迭代器的循環(huán)體,都不要向迭代器所屬的容器添加元素
C++中string對(duì)象大小比較蒸痹,兩字符串自左向右逐個(gè)字符相比(按ASCII值大小相比較)
使用數(shù)組初始化vector對(duì)象:
int int_arr[] = {0,1,2,3,4,5};
//C++11中新定義的begin()和end()函數(shù)
vector<int> v(begin(int_arr), end(int_arr));
內(nèi)存的基本單元是位(bit)春弥,相當(dāng)于開(kāi)關(guān),關(guān)=0叠荠、開(kāi)=1
字節(jié)(byte)通常指8位的內(nèi)存單元
1 KB = 1024 BYTE
1 MB = 1024 KB
sizeof()返回字節(jié)數(shù)
VS屏蔽4786警告 #pragma warning (disable:4786)
頭文件climits定義了所有C++符號(hào)常量 例如:#define INT_MAX 32767
cout << hex; 以十六進(jìn)制數(shù)輸出
cout << dec; 以十進(jìn)制數(shù)輸出
cout << oct; 以八進(jìn)制數(shù)輸出
不要返回一個(gè)局部變量的指針或引用惕稻,因?yàn)榈玫降闹羔標(biāo)竷?nèi)容在函數(shù)結(jié)束后就已變了
//此引用不會(huì)修改實(shí)參的值,因?yàn)橛衏onst限制蝙叛,當(dāng)程序試圖修改str時(shí)俺祠,編譯器將報(bào)錯(cuò)
char * StringToCharPtr(const string &str);
//此引用將會(huì)改變實(shí)參的值
char * StringToCharPtr(string &str);
盡可能的將引用參數(shù)聲明為const
為什么要返回引用? 效率更高借帘,例如:
double m = sqrt(16.0);
傳統(tǒng)返回:計(jì)算return后的表達(dá)式蜘渣,將結(jié)果4復(fù)制到一個(gè)臨時(shí)位置,然后再傳遞給m
返回引用:計(jì)算return后的表達(dá)式肺然,將結(jié)果直接復(fù)制給接收的變量
注: 返回引用的函數(shù)實(shí)際上是被引用的變量的別名
避免返回臨時(shí)變量的引用和指向臨時(shí)變量的指針
因?yàn)榕R時(shí)變量存放在棧中蔫缸,函數(shù)執(zhí)行完畢會(huì)自動(dòng)銷毀,所以其引用和指針包含的數(shù)據(jù)都是錯(cuò)的
比如只是在函數(shù)中定義 int a际起;那這是個(gè)臨時(shí)變量是在棧中的拾碌,使用完自動(dòng)銷毀;
比如定義是int *a; a=new int[10]; 那這個(gè)是分配在堆中的街望,使用完需要手動(dòng)釋放校翔,防止內(nèi)存泄漏。
1灾前、棧區(qū)(stack)編譯器自動(dòng)分配釋放防症,存放函數(shù)的參數(shù)值,局部變量的值等
2哎甲、堆區(qū)(heap) 程序員分配釋放蔫敲,若程序員不釋放,程序結(jié)束時(shí)可能由os回收
何時(shí)使用引用參數(shù)炭玫?
程序員能夠修改調(diào)用函數(shù)中的數(shù)據(jù)對(duì)象
通過(guò)傳遞引用而不是整個(gè)數(shù)據(jù)對(duì)象奈嘿,可以提高程序的運(yùn)行速度
什么時(shí)候使用按值傳遞?什么時(shí)候使用引用參數(shù)吞加?什么時(shí)候使用指針參數(shù)裙犹?
1.數(shù)據(jù)對(duì)象很小酝惧,如內(nèi)置數(shù)據(jù)類型或小型結(jié)構(gòu),則按值傳遞
2.數(shù)據(jù)對(duì)象是數(shù)組伯诬,則使用指針晚唇,因?yàn)橹羔樋梢砸苿?dòng)并將指針聲明為指向const的指針
3.數(shù)據(jù)對(duì)象是較大的結(jié)構(gòu),則使用const指針或const引用盗似,節(jié)省復(fù)制結(jié)構(gòu)的時(shí)間和空間
4.數(shù)據(jù)對(duì)象是類哩陕,則使用const引用,類設(shè)計(jì)的語(yǔ)義常要求使用引用赫舒,這是C++新增這項(xiàng)特性的主要原因悍及。因此,傳遞類對(duì)象的標(biāo)準(zhǔn)方式是按引用傳遞接癌。
如果 int sub(); 是一個(gè)函數(shù)心赶,則sub即是該函數(shù)的內(nèi)存地址
press(sub()) //傳遞函數(shù)sub()的返回值給函數(shù)press()
press(sub) //傳遞函數(shù)sub()的地址給函數(shù)press()
函數(shù)指針的聲明:
double pam(int);
double (pf)(int);
pam是函數(shù),所以(pf)也是函數(shù)缺猛。 (pf)是函數(shù)缨叫,則pf就是函數(shù)指針
為了提供正確的運(yùn)算符優(yōu)先級(jí),必須在聲明中使用括號(hào)將pf括起來(lái)荔燎。括號(hào)的優(yōu)先級(jí)比運(yùn)算符高耻姥,
因此,pf(int)意味著pf(int)是一個(gè)返回double指針的函數(shù)有咨,而(pf)(int)意味著pf是一個(gè)指向函數(shù)的指針
double (pf)(int); 意味著pf是一個(gè)指向函數(shù)的指針
double pf(int); 意味著pf(int)是一個(gè)返回double指針的函數(shù)
正確的聲明pf后琐簇,便可以將相應(yīng)函數(shù)的地址賦給它:
double pam(int);
double (pf)(int);
pf = pam;
注意,pam()的參數(shù)和返回值必須與pf相同座享,否則編譯器將拒絕這種賦值
typedef double real 創(chuàng)建double類型的別名"real"
"Pizaa" C++解讀"Pizaa"為其元素的第一個(gè)內(nèi)存地址婉商,為取值,所以*"Pizaa" = P
"Taco"[2] C++解讀"Taco"為其元素的第一個(gè)內(nèi)存地址渣叛,所以"Taco"[2] = c
也就是說(shuō)丈秩,字符串常量的行為與數(shù)組相同
char name[30];
string str = "James";
name = str; 此種賦值的方式是錯(cuò)誤的,正確的賦值方法應(yīng)該是: strcpy/strcpy_s(name,str);
在VS2015中诗箍,編譯strcpy函數(shù)會(huì)報(bào)C4996
'strcpy': This function or variable may be unsafe. Consider using strcpy_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.
將strcpy(name,str)修改為strcpy_s(name,str);
類似的錯(cuò)誤癣籽,也同樣發(fā)生在其它很多的老式C語(yǔ)言函數(shù)身上挽唉,解決辦法是更改為C++的函數(shù)版本.
在C語(yǔ)言中數(shù)組是不容許整體復(fù)制的滤祖!
故: name = str; / MyStruct.name=str; 這樣的數(shù)組賦值是不正確的
表明上看這句話只是把一個(gè)地址給他,實(shí)際上要求的是數(shù)組的整體復(fù)制瓶籽。
因?yàn)閿?shù)組的地址是const的匠童,不能改變。數(shù)組是可以當(dāng)指針用塑顺,但只能是const指針汤求。
兩種解決方法:
1俏险、把char name[30]修改為char* name;
2、把equal函數(shù)中的 get.name=str;修改為 strcpy(get.name, str);
size()是取字符串長(zhǎng)度的扬绪,跟length()用法相同
length()是沿用C語(yǔ)言的習(xí)慣而保留下來(lái)的竖独,string類最初只有l(wèi)ength(),引入STL之后挤牛,為了兼容又加入了size()莹痢,
它是作為STL容器的屬性存在的,便于符合STL的接口規(guī)則墓赴,以便用于STL的算法竞膳。
string類的size()/length()方法返回的是字節(jié)數(shù),不管是否有漢字诫硕。
sizeof(...)是運(yùn)算符坦辟,其值在編譯時(shí)即計(jì)算好了,參數(shù)可以是數(shù)組章办、指針锉走、類型、對(duì)象藕届、函數(shù)等
它的功能是:獲得保證能容納實(shí)現(xiàn)所建立的最大對(duì)象的字節(jié)大小挠日。由于在編譯時(shí)計(jì)算,
因此sizeof不能用來(lái)返回動(dòng)態(tài)分配的內(nèi)存空間的大小
類型強(qiáng)制轉(zhuǎn)換:
C風(fēng)格:
int x = 65;
char c = (char)x;
C++風(fēng)格:
int x = 90;
char c = char(x);
static_cast<char>(x); char = 轉(zhuǎn)換后的類型 x = 待轉(zhuǎn)換的變量或表達(dá)式
C++11新特性:
typedef double wages; //wages是double的別名
typedef double wages base, *p; //base是double的別名翰舌,p是double*的別名
using SI = Sales_item; //C++11新標(biāo)準(zhǔn)嚣潜,SI是Sales_item的別名
SI item1,item2; //等價(jià)于Sales_item item1椅贱,item2;
aoto value = val1 + val2; //根據(jù)val1 + val2的結(jié)果推斷value的類型
decltype(function()) sum = x; //sum的類型就是function()函數(shù)的返回值類型懂算,編譯器不會(huì)執(zhí)行function()函數(shù)
decltype(expression) var 適用于模板函數(shù)內(nèi)無(wú)法確定返回值類型的情況
template <typename T1, typename T2>
void templateFunction(T1 x, T2 y)
{
decltype(x + y) sum = x + y; //如果沒(méi)有decltype sum則無(wú)法確定究竟是什么類型
//auto sum = x + y; 此問(wèn)題用auto關(guān)鍵字也有同樣的效果
}
auto templateFunction(T1 x, T2 y) -> decltype(x + y) 解決無(wú)法定義返回值類型的問(wèn)題
{
decltype(x + y) sum = x + y; //如果沒(méi)有decltype sum則無(wú)法確定究竟是什么類型
//auto sum = x + y; 此問(wèn)題用auto關(guān)鍵字也有同樣的效果
int *p = new int;
delete p;
p = nullptr;
最好將釋放的指針設(shè)置為空,以便程序后續(xù)可以檢測(cè)到該指針已經(jīng)被釋放
for(declaration : expression) //迭代expression對(duì)象中的所有元素
{
statement
}
string str = "some string!"; //迭代str中的所有元素
for (auto c : str)
cout << c << endl;
如果我們想要修改str的元素該如何操作呢庇麦?答案是利用引用:
for (auto &c : str) 此時(shí)c是str當(dāng)前元素的引用计技,所以修改c,也就是修改了str內(nèi)的元素山橄,示例:
//迭代str中的所有元素垮媒,并且當(dāng)元素為小寫(xiě)字母時(shí),通過(guò)修改str元素的引用c來(lái)達(dá)到修改str元素為大寫(xiě)字母的目的
string str = "Some String!";
for (auto &c : str)
{
if (islower(c))
{
c = toupper(c);
}
cout << c << " ";
}
C++11定義了begin()和end()函數(shù)航棱,使用方法和STL中的同名類函數(shù)類似睡雇,示例:頭文件 <iterator>
int ia[] = {0,1,2,3,4,5,6,7,8,9};
int *beg = begin(ia); //指向ia首元素的指針
int *last = end(ia); //指向數(shù)組尾元素的下一位置的指針(和STL中vector<int> v; v.end()的意思是一樣的)
常用英文單詞:
英文 | 中文 |
---|---|
preprocessor | 預(yù)處理器 |
header guard | 頭文件保護(hù)符 |
header | 頭文件 |
expression | 表達(dá)式 |
initialize | 初始化 |
identifier | 標(biāo)識(shí)符 |
operator | 運(yùn)算符 |
scope | 作用域 |
null pointer | 空指針 |
assignment | 賦值 |
comments | 注釋 |
variable | 變量 |
function | 函數(shù) |
method | 方法 |
member | 成員 |
object | 對(duì)象 |
argument | 實(shí)參 |
declaration | 聲明 |
definition | 定義 |
condition | 條件 |
default | 默認(rèn) |
value | 值 |
reference | 引用 |
alias | 別名 |
bind | 綁定 |
integral | 整型 |
convert | 轉(zhuǎn)換 |
vector | 向量 |
container | 容器 |
index | 索引 |
address | 地址 |
library | 庫(kù) |
buffer | 緩沖 |
block | 程序塊 |
manipulator | 操作符 |
built-in type | 內(nèi)置類型 |
data structure | 數(shù)據(jù)結(jié)構(gòu) |
edit-compile-debug | 編輯-編譯-調(diào)試 |