chapter-6

C++ Primer第六章!

#include "stdafx.h" 
#include<iostream>
#include<string>
#include<vector>
#include<initializer_list>          //實(shí)參數(shù)量未知乳讥,但是類型相同
#include<cassert>               //調(diào)式頭文件柱查,assert和NDEBUG

using namespace std;
int fact_sample(int val)
{
    int ret = 1;
    while (val > 1)
    {
        ret = ret*val;
        --val;
    }
    return ret;
}
int fact_iterator(int val)
{
    int tmp = val;
    if(val>1)
        return tmp*fact_iterator(--val);            //此處不能使用val*fact_iterator(--val),val的值會(huì)改變云石,造成表達(dá)式邏輯錯(cuò)誤唉工!
    else
    {
        return val;
    }
}

int factorial(int val)
{
    if (val>1)
        return val*fact_iterator(val-1);            //同int fact_iterator(int val)。
    else
    {
        return 1;
    }
}

int fact_for(int val)
{
    int ret = 1;
    for (int i = 1; i <= val; ++i)
    {
        ret = ret*i;
    }
    return ret;
}

size_t count_calls()
{
    static size_t ctr = 0;                      //局部靜態(tài)對(duì)象汹忠,直到程序終止才被銷毀
    return ++ctr;
}
void reference_fun(int &val)
{
    --val;
}
void p_fun(int *ip)
{
    *ip = *ip - 1;
}

bool isShorter(const string &s1, const string &s2)          //比較兩個(gè)string對(duì)象的長(zhǎng)度酵紫,string可能非常長(zhǎng)告嘲,建議使用引用!
{                                                           //有的類型不支持拷貝(iostream奖地,其同時(shí)也不支持const)橄唬,則只能通過(guò)引用傳遞!
    return s1.size() < s2.size();
}

void print_arry(const int *arry)                            //等價(jià)于const int[],const int[10].不允許拷貝數(shù)組参歹,但是形參還是可以寫成數(shù)組形式仰楚,其實(shí)質(zhì)是const int*
{
    cout << arry[0] << endl;
}

void print_char(const char *cp)
{
    if (cp)
        while (*cp)
            cout << *cp++;
}

void print_iter(const int *beg, const int *end)
{
    while (beg != end)
        cout << *beg++ << endl;
}

void print_count(const int ia[], size_t size)
{
    for (size_t i = 0; i != size; ++i)
    {
        cout << ia[i] << endl;
    }
}

void print_reference(int(&arr)[2])
{
    for (auto elem : arr)
        cout << elem << endl;
}

void print_mulit_ptr(int(*matptr)[2],int rowsize)       //指向含有10個(gè)整數(shù)的數(shù)組的指針。而int *matptr[10]表示10個(gè)指針構(gòu)成的數(shù)組
// 等價(jià)于void print_mulit_ptr(intmatptr[][2],int rowsize)
{
    for (int i = 0; i < rowsize; ++i)
    {
        auto *beg = begin(*matptr);                     //由于已知數(shù)組的大小犬庇,也可以直接使用僧界。
        while (beg!=end(*matptr))
        {
            cout << *beg << "+";
            ++beg;
        }
        cout << endl;
        ++matptr;
    }
}

void print_msg(initializer_list<string> lst)
{
    for (auto beg = lst.begin(); beg != lst.end(); ++beg)       //可以使用范圍for循環(huán)處理其中的元素
        cout << *beg << " ";
    cout << endl;
}

const string &shortString(const string &s1, const string &s2)
{
    return s1.size() <= s2.size() ? s1 : s2;
}

void print_ret()
{
    return;
}

char &get_value(string &str, string::size_type ix)
{
    return str[ix];
}

vector<string> process_return()
{
    return { "aaa","bbb","ccc" };           //也可以返回renturn {};返回指定類型空vector
}

int odd[2] = { 13,14 };
int even[2] = { 52,93 };
decltype(odd) *arrptr(int i)
{
    return (i % 2) ? &odd : &even;          //int (*p)[2]=&odd;指向10個(gè)整數(shù)的數(shù)組的定義臭挽。
}

void print_overload()
{
    cout << "Test" << endl;;
}
void print_overload(const char *cp)
{
    cout<<*cp<<endl;
}
void print_overload(const char *cp,string::size_type sz)
{
    for (unsigned int i = 0; i < sz; ++i)
    {
        cout << cp[i];
    }
    cout << endl;                               //最好不在函數(shù)中定義輸出的格式捂襟。
}

const string &shorterString(const string &s1, const string &s2)
{
    return s1.size() < s2.size() ? s1 : s2;
}
string &shorterString(string &s1, string &s2)
{
    auto &r = shorterString(const_cast<const string&>(s1), const_cast<const string&>(s2));
    return const_cast<string&>(r);
}

using sz = string::size_type;// size_t是全局定義的類型;size_type是STL類中定義的類型屬性欢峰,用以保存任意string和vector類對(duì)象的長(zhǎng)度葬荷!數(shù)組下表是size_t,而容器是size_type纽帖!
string screen(sz ht = 24, sz wid = 80, char background = ' ')       //一旦某個(gè)形參被賦予了默認(rèn)值宠漩,他后面的所有形參都必須有默認(rèn)值。
{
    return " ";                                                             //如果進(jìn)行多次聲明默認(rèn)實(shí)參函數(shù)懊直,則函數(shù)的后續(xù)聲明只能為沒(méi)有默認(rèn)實(shí)參的形參添加默認(rèn)值扒吁,且該形參右側(cè)所有形參都必須有默認(rèn)值!
}

inline const int &max_numbers(const int &a, const int &b)
{
    return a < b ? b : a;
}

constexpr size_t arr_count(size_t cnt)
{
    return 10 * cnt;
}

int addb(const int &a, const int &b)
{
    return(a + b);
}
int(*p_addb)(const int &a, const int &b);       //p_addb指向函數(shù)的指針室囊,其中該函數(shù)的兩個(gè)參數(shù)為const int的引用雕崩,返回值為int。

void  print_addb(ostream &os, int(*print_addb)(const int &a, const int &b),const int a=3,const int b=4)
{
    os << (*p_addb)(a,b) << endl;
}

int main()
{
    int j_sample = fact_sample(5);              //調(diào)用函數(shù)融撞,實(shí)參可以隱式轉(zhuǎn)換為形參E翁(形參初始化的機(jī)理和變量初始化一樣)
    cout << j_sample << endl;                   //函數(shù)的返回類型不能是數(shù)組和函數(shù),但可以是指向數(shù)組或函數(shù)的指針
    int j_iterator = fact_iterator(5);          //在頭文件中放函數(shù)聲明懦铺,在源文件中包含頭文件,并定義函數(shù)支鸡。
    cout << j_iterator << endl;
    int j_for = fact_for(5);
    cout << j_for << endl;

    int j_reference = 5;
    reference_fun(j_reference);                 //引用傳遞冬念,形參初始化的機(jī)理和變量初始化一樣
    cout << j_reference << endl;

    int j_p = 5;                                //指針傳遞,形參初始化的機(jī)理和變量初始化一樣
    p_fun(&j_p);
    cout << j_p << endl;

    //void fcn(const int i){}
    //void fcn(int i){}             兩個(gè)函數(shù)是一樣的牧挣,在形參拷貝初始化時(shí)急前,忽略了它的頂層const,因此給函數(shù)形參是一樣的瀑构!
    //C++允許通過(guò)字面值初始化常量引用裆针,而不允許初始化普通引用!

    int i_arry[10] = { 0,1,2,3 };
    print_arry(i_arry);

    //使用數(shù)組時(shí)確保不會(huì)越界刨摩,常見(jiàn)3種常用的技術(shù)
    
    //數(shù)組本身包含一個(gè)結(jié)束標(biāo)記,例如C風(fēng)格字符串
    char *p_char = "abc";
    print_char(p_char);

    //begin和end函數(shù)
    int j_arry[2] = { 1,2 };
    print_iter(begin(j_arry), end(j_arry));

    //顯示傳遞一個(gè)數(shù)組大小
    int j_count[2] = { 9,8 };
    print_count(j_count, end(j_count) - begin(j_count));

    //數(shù)組引用形參
    int j_refer[2] = { 7,6};
    print_reference(j_refer);

    //傳遞多維數(shù)組
    int j_mulit_arry[2][2] = { 1,2,3,4 };
    print_mulit_ptr(j_mulit_arry, 2);
    
    //可變形參的函數(shù)世吨,1澡刹、如果實(shí)參類型相同可以使用initializer_list;2耘婚、可變參數(shù)模版罢浇?
    //initializer_list<T> lst;
    //initializer_list<T> lst{a,b,c};   lst對(duì)象中的元素永遠(yuǎn)是常量值沐祷,即abc為const嚷闭。
    //lst2=lst;                         拷貝或賦值一個(gè)initializer_list對(duì)象不會(huì)拷貝列表中的元素,原始列表和副本共享元素赖临。
    //lst.size();
    //lst.begin();                      返回指向lst中首元素的指針胞锰。
    //lst.end();
    print_msg({ "aa","bb","cc" });      //向initializer_list形參中傳遞一個(gè)值的序列,必須把序列放在一對(duì)花括號(hào)內(nèi)兢榨。

    //返回return
    //無(wú)返回值函數(shù)嗅榕,可以使用return語(yǔ)句提前退出函數(shù)
    print_ret();

    //有返回值函數(shù),返回類型應(yīng)與函數(shù)類型一致色乾。返回一個(gè)值的方式和初始化一個(gè)變量或形參的方式完全一樣誊册!
    string s_short1 = "aaa", s_short2 = "bbbb";
    cout << shortString(s_short1, s_short2) << endl;

    //返回局部變量時(shí),則返回的是局部變量的副本(未命名臨時(shí)變量)暖璧。請(qǐng)一定不要返回局部對(duì)象的引用或指針0盖印!澎办!

    //引用返回值嘲碱,返回引用的函數(shù)得到左值,其他返回類型得到右值
    string s_value("aaaaa");
    get_value(s_value, 2) = 'B';
    cout << s_value << endl;

    //列表初始化返回值
    vector<string> err_msg_return = process_return();

    //主函數(shù)main的返回值
    //mian函數(shù)的返回值可以看作狀態(tài)指示器局蚀,返回0表示執(zhí)行成功麦锯,返回其他值表示失敗。
    //cstdlib中定義了兩個(gè)預(yù)處理變量琅绅,EXIT_FAILURE,EXIT_SUCCESS扶欣。

    //遞歸,函數(shù)調(diào)用自身千扶,遞歸函數(shù)
    cout << factorial(5) << endl;

    // 返回?cái)?shù)組指針
    using arrT = int[2];    //等價(jià)于typedef int arrT[10]
    //arrT* func(int i),等價(jià)于int (*func(int i))[10],也可以使用C++新規(guī)定:位置返回類型
    //auto func(int i) -> int(*)[10];
    //如果已知函數(shù)返回的指針將指向哪個(gè)數(shù)組料祠,可以使用decltype推斷
    int i_decl = 2;
    int (*out_decl)[2] = arrptr(i_decl);
    for (int i = 0; i < 2; ++i)
    {
        cout << (*out_decl)[i] << " ";          //int (*p)[2]=&odd;p為指針,指向10個(gè)整數(shù)的數(shù)組澎羞。
    }
    cout << endl;

    //重載函數(shù),在形參數(shù)量或類型上有所不同髓绽。盡量只重載那些確實(shí)非常相似的操作
    const char *p_overload = "abcdefg";
    print_overload();
    print_overload(p_overload);
    print_overload(p_overload, 3);
    //頂層const形參,函數(shù)等價(jià)妆绞。底層const顺呕,函數(shù)可重載枫攀。頂層const只決定了在函數(shù)體內(nèi)是否可以改變形參值,而不影響傳入的實(shí)參株茶。
    //int lookup(int),int lookup(const int);    int lookup(int*),int lookup(int *const)来涨,頂層const等價(jià)
    //int lookup(int&),int lookup(const int&);  int lookup(int*),int lookup(const int*),如果形參是某種類型的指針或引用忌卤,則通過(guò)區(qū)分其指向的是常量對(duì)象還是非常量對(duì)象可以實(shí)現(xiàn)函數(shù)重載(底層const)扫夜。

    //const_cast和重載
    //shorterString,有什么特別作用嗎?當(dāng)使用非常量實(shí)參驰徊,想得到非常量的引用時(shí)笤闯,此時(shí)使用shorterString,定義2個(gè)重載函數(shù)棍厂。同時(shí)颗味,重載函數(shù)應(yīng)該避免強(qiáng)制類型轉(zhuǎn)換!

    //默認(rèn)實(shí)參牺弹,調(diào)用含有默認(rèn)實(shí)參的函數(shù)浦马,可以包含該實(shí)參,也可以省略該實(shí)參张漂。
    string window;
    window = screen();
    window = screen(255, 255, '+');
    //window=screen(,,'+')  錯(cuò)誤行為晶默,在設(shè)計(jì)默認(rèn)實(shí)參函數(shù)時(shí),盡量讓使用默認(rèn)值的形參放在后面航攒,不適用默認(rèn)值的形參放在前面磺陡!
    
    //默認(rèn)實(shí)參初始值含義?

    //內(nèi)聯(lián)函數(shù)漠畜,適用于節(jié)省開(kāi)銷币他、流程直接、頻繁調(diào)用的函數(shù)
    int inline_a = 3, inline_b = 5;
    cout << max_numbers(inline_a, inline_b)<<endl;              //等價(jià)于cout<<(a < b ? b : a)<<endl;
    
    //constexpr函數(shù)憔狞,函數(shù)的返回類型和所有形參的類型都得是字面值類型(內(nèi)置類型蝴悉、引用、指針)瘾敢,而函數(shù)體中必須有且只有一條return語(yǔ)句拍冠。
    int arr_constexpr1[arr_count(2)];
    size_t i_constexpr = 2;
    //int arr_constexpr2[arr_count(i_constexpr)];           arr_count返回值不為常量表達(dá)式。

    //調(diào)試幫助簇抵,assert和NDEBUG
    assert(3 > 2);                                          //如果表達(dá)式為假庆杜,則輸出信息并終止程序,可以用#define語(yǔ)句定義NDEBUG語(yǔ)句正压,關(guān)閉調(diào)式狀態(tài)欣福!

    //函數(shù)指針责球,指向函數(shù)而非對(duì)象
    int a_func = 1, b_func = 2;
    p_addb = addb;                                          //等價(jià)于p_addb=&addb.另外可以為p_addb賦值nullptr焦履,表示沒(méi)有指向任何一個(gè)函數(shù)拓劝。
    cout << addb(a_func, b_func) << endl;
    cout << p_addb(a_func, b_func) << endl;
    cout << (*p_addb)(a_func, b_func) << endl;              //等價(jià)于上面調(diào)用語(yǔ)句
    //使用函數(shù)指針作為形參, 將函數(shù)作為實(shí)參
    print_addb(cout, addb);
    print_addb(cout, addb,1,9);
    //返回指向函數(shù)的指針
    using F = int(int);
    using PF = int(*)(int);
    //PF f1(int),f1返回指向函數(shù)的指針
    //F *f1(int),f1返回指向函數(shù)的指針
    //auto f1(int)->int(*)(int),返回指向函數(shù)的指針嘉裤。
    //也可以使用decltype推斷函數(shù)的類型郑临,得到形如F形式,接著聲明函數(shù)屑宠。

    cin.ignore();

    return 0;
}

//函數(shù)包含返回類型聲明厢洞、函數(shù)名、形參典奉、實(shí)參躺翻、函數(shù)體等等部分,另外可以對(duì)函數(shù)進(jìn)行重載卫玖。
//內(nèi)聯(lián)函數(shù)可以避免常見(jiàn)的函數(shù)調(diào)用開(kāi)銷公你!
//省略符形參是什么鬼?

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末假瞬,一起剝皮案震驚了整個(gè)濱河市陕靠,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌脱茉,老刑警劉巖剪芥,帶你破解...
    沈念sama閱讀 212,816評(píng)論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異琴许,居然都是意外死亡税肪,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,729評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門虚吟,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)寸认,“玉大人串慰,你說(shuō)我怎么就攤上這事“铞辏” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 158,300評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵庆捺,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我滔以,道長(zhǎng),這世上最難降的妖魔是什么你画? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 56,780評(píng)論 1 285
  • 正文 為了忘掉前任桃漾,我火速辦了婚禮,結(jié)果婚禮上拟逮,老公的妹妹穿的比我還像新娘撬统。我一直安慰自己,他們只是感情好敦迄,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,890評(píng)論 6 385
  • 文/花漫 我一把揭開(kāi)白布恋追。 她就那樣靜靜地躺著,像睡著了一般罚屋。 火紅的嫁衣襯著肌膚如雪苦囱。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 50,084評(píng)論 1 291
  • 那天脾猛,我揣著相機(jī)與錄音沿彭,去河邊找鬼。 笑死尖滚,一個(gè)胖子當(dāng)著我的面吹牛喉刘,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播漆弄,決...
    沈念sama閱讀 39,151評(píng)論 3 410
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼睦裳,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了撼唾?” 一聲冷哼從身側(cè)響起廉邑,我...
    開(kāi)封第一講書(shū)人閱讀 37,912評(píng)論 0 268
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎倒谷,沒(méi)想到半個(gè)月后蛛蒙,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,355評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡渤愁,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,666評(píng)論 2 327
  • 正文 我和宋清朗相戀三年牵祟,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片抖格。...
    茶點(diǎn)故事閱讀 38,809評(píng)論 1 341
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡诺苹,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出雹拄,到底是詐尸還是另有隱情收奔,我是刑警寧澤,帶...
    沈念sama閱讀 34,504評(píng)論 4 334
  • 正文 年R本政府宣布滓玖,位于F島的核電站坪哄,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜翩肌,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 40,150評(píng)論 3 317
  • 文/蒙蒙 一饰剥、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧摧阅,春花似錦、人聲如沸绷蹲。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,882評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)拦英。三九已至,卻和暖如春灾常,著一層夾襖步出監(jiān)牢的瞬間铃拇,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,121評(píng)論 1 267
  • 我被黑心中介騙來(lái)泰國(guó)打工雕什, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留贷岸,地道東北人磷雇。 一個(gè)月前我還...
    沈念sama閱讀 46,628評(píng)論 2 362
  • 正文 我出身青樓唯笙,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親尿庐。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,724評(píng)論 2 351

推薦閱讀更多精彩內(nèi)容