《C++ Primer》讀書筆記


第一章 開始

類型:程序所處理的數據都保存在變量中,而每個變量都有自己的類型

內置類型:語言自身定義的類型(而形如string等類型都是標准庫定義的)

main的返回值:0表示成功,非0指出錯誤類型

從命令行運行編譯器

for語句

術語表:緩沖區、cerr、clog、表達式

 

第一部分 C++基礎

第二章 變量和基本類型

幾種字符類型:char 、wchar_t 、char16_t 、char32_t

內置類型的機器實現:內置類型如何在內存存放

將負數轉換為無符號類型:結果為無符號數的模加上這個負數

字面值常量:每個字面值常量都對應一種數據類型、字符串字面值(實際是由常量字符構成的數組),可以指定字面值的類型

轉義序列:回車\r、換行\n

對象:指一塊能存儲數據並具有某種類型的內存空間

初始化:列表初始化、默認初始化

變量聲明和定義的關系:分離式編譯、extern

復合類型:基於其他類型定義的類型

聲明符:聲明語句int &r;中,&r為聲明符,聲明符命名了一個變量,也指定該變量為與基本數據類型(此例為int)有關的某種類型

引用&引用類型:我們稱r為引用或引用類型

指針:*p為聲明符,p是變量名,我們稱p為指針或指針變量

const限定符:常量引用(對常量的引用)、可以將一個常量引用綁定到變量、字面值、表達式(因為不允許通過該引用修改這些對象)

頂/底層const:執行對象拷貝時的限制

constexpr:聲明常量

decltype類型指示符:返回表達式的類型

編寫自己的頭文件:頭文件通常包含那些只能定義一次的實體,如類、const、constexpr變量

預處理變量:#ifdef、#ifndef、#endif

術語表:常量表達式、頭文件保護符、未定義、void*

 

第三章 字符串、向量和數組

標准庫類型string

string::size_type類型:string的size函數返回的是一個string::size_type類型的值;string類及其他大多數標准庫類型都定義了幾種配套的類型,體現了標准庫類型與機器無關的特性,類型size_type即是其中的一種,通過域操作符來表明名字size_type是在類string中定義的、

處理string對象中的字符:cctyoe頭文件中的函數

迭代器:使迭代器失效的操作

數組:數組的引用,數組的下標類型為size_t,數組名和指針

標准庫函數begin和end

c_str函數:返回一個C風格的字符串,返回結果是一個指針,該指針指向一個以空字符結束的字符數組,指針的類型是const char*

使用數組初始化vector對象:vector<int> vec(begin(arr), end(arr));

術語表:直接初始化、值初始化、->運算符

 

第四章 表達式

表達式:最小的計算單元。一個表達式包含一個或多個運算對象,通常還包含一個或多個運算符。表達式求值會產生一個結果。

字面值和變量是最簡單的表達式,其結果就是字面值和變量的值。

表達式本身也可以作為運算對象。

左值和右值

運算符的優先級和結合律

位運算符:檢查和設置二進制位

類型轉換:顯示轉換(static_cast)

術語表:復合表達式、整型提升、短路求值

 

第五章 語句

表達式語句:在一個表達式的末尾加上分號

switch語句:對括號里的表達式求值,然后和各case標簽的值比較

do while語句:先執行后判斷;條件為假終止循環

goto語句:容易引發錯誤,慎用

try語句塊:throw表達式、catch子句、異常類

術語表:塊、帶標簽語句、異常聲明、terminate

 

第六章 函數

形參名是可選的:無法使用未命名的形參

局部對象:自動對象、局部靜態對象

引用形參:是對應實參的別名,可避免拷貝

const形參:p190

數組引用形參:形參是數組的引用,有限制(大小固定)

main的形參的使用:處理命令行選項

可變形參:initializer_list類型的形參、省略符形參

返回值:初始化調用點的臨時量

引用返回左值:返回引用的函數

返回花括號包圍的值列表

主函數main的返回值

返回數組指針使用的類型別名:尾置返回類型、decltype

重載、內聯函數、默認實參

constexpr函數:返回常量表達式的函數,被隱式地聲明為內聯函數

調試幫助:assert、NODEBUG

函數指針

術語表:二義性調用、assert、候選函數、可行函數

 

第七章 類

使用類定義自己的數據類型

this:一個(指向類類型非常量版本的)常量指針,總是指向調用對象

const成員函數:修改this指針的類型(把this設置為指向常量的指針),故該函數不能改變調用它的對象的內容

定義/初始化/拷貝/賦值/銷毀 類的對象

構造函數:類控制其對象的初始化過程的方式

合成的默認構造函數:如果不存在類內的初始值,則默認初始化該成員

構造函數初始值列表:后執行函數體

拷貝對象:初始化、傳值調用、返回一個對象

賦值操作:使用了賦值運算符時

我們不定義上面這些操作(初始化/拷貝/賦值/銷毀),編譯器將替我們合成它們

封裝性:使用訪問說明符,使用戶不可訪問類的部分成員,public成員定義類的接口,private部分封裝了類的實現細節

友元:訪問相關聯的類的私有成員,友元類的成員函數也可訪問

成員函數&內聯:定義在類內部的成員函數是自動inline的,而在類外定義的成員函數必須用inline關鍵字修飾

可變數據成員:mutable關鍵字聲明;即使它是const對象的成員也是可變的

基於const的重載:對某個對象調用重載成員函數時,將根據該對象是否是const決定調用哪個版本

不完全類型:前向聲明的類(僅聲明類),不能定義以不完全類型作為參數或返回類型的函數

委托構造函數

explicit:轉換構造函數、一步類類型轉換

聚合類、字面值常量類

類的靜態成員:不能在類的內部初始化靜態成員,但可以為constexpr的靜態成員提供const整型的類內初始值

術語表:抽象數據類型、顯式構造函數、接口、名字查找、=default

 

第二部分 C++標准庫

第八章 IO庫

通過一族定義在標准庫中的類型來處理IO

IO類:istream/ostream/iostream、ifstream/ofstream/fstream、istringstream/ostringstream/stringstream

IO類型間的關系:類型ifstream和istringstream都繼承自istream,可將派生類對象當作其基類對象使用

IO對象無拷貝或賦值:不能拷貝或對IO對象賦值,即形參或返回類型必須是引用類型

IO庫條件狀態:可被任何流類使用的一組標志和函數,指出給定流是否可用

輸出緩沖區:保存程序讀寫的數據,可以管理該緩沖區

文件輸入輸出:綁定文件的方式、按指定mode打開文件、關閉關聯文件close

文件模式:類fstream定義的一組標志,在打開文件時指定,用來控制文件如何被使用

術語表:字符串流、stringstream

 

第九章 順序容器

類型:vector、deque、list、forward_list、array、string

array:一種數組類型,其對象大小是固定的

使用元素類型的默認構造函數:只接受容器大小參數時,類必須要有默認構造函數

容器操作:類型別名,支持<、<=運算符,所有容器都支持相等運算符

emplace操作:構造而非拷貝元素

使迭代器失效的容器操作:p315

容器適配器:為容器操作定義了不同的接口,來與容器類型適配

術語表:適配器、左閉合區間

 

第十章 泛型算法

標准庫容器定義了很少的操作(添加、刪除元素,訪問首尾元素等),有更多的操作(如查找特定元素、重排元素等)需要通過算法實現。

迭代器令算法不依賴於容器,但算法依賴於元素類型的操作

算法:find、count、accumulate、equal、fill、replace、sort、unique、stable_sort、for_each、transform

插入迭代器:一種向容器中添加元素的迭代器,back_iterator

謂詞作為參數:謂詞是一個可調用的表達式,其返回結果是一個能用作條件的值,如cmp(返回能作為條件的bool值,能調用cmp(a, b))

標准庫算法或使用一元謂詞或使用二元謂詞,一元謂詞意味着該謂詞只能接受一個參數

lambda表達式:當算法要求使用X元謂詞,而實際使用到的謂詞接受的參數個數大於X時,我們需要使用lambda表達式

可調用對象:可對其使用調用運算符的對象,如函數、函數指針、lambda表達式、重載了函數調用運算符的類

bind函數:解決謂詞參數數目問題

插入迭代器:back_inserter、front_inserter、inserter

iostream迭代器:將對應的流當做一個特定類型的元素序列來處理

反向迭代器:需要遞減運算符

_copy版本的算法:將元素寫到一個指定的輸出目的位置

_if版本的算法:接受一個謂詞

鏈表類型list和forward_list優先使用成員函數形式的算法:不使用通用算法,因為它們不支持隨機訪問迭代器

術語表:istream_iterator、ostream_iterator、迭代器類別

 

第十一章 關聯容器

元素按關鍵字來保存和訪問

類型:map、set、multimap、multiset、及其相應的無需版本(前面加unordered_)

map:關鍵字-值對的集合,關聯數組

set:支持高效的關鍵字查詢操作

pair類型:map中的元素的類型,first成員保存關鍵字,second成員保存對應的值

multi:允許多個元素具有相同的關鍵字

關聯容器不支持順序容器的位置相關的操作(如push_back等),因為其中的元素是根據關鍵字存儲的

關鍵字類型的要求:該類型要求定義了“行為正常”的<運算符

自定義組織一個容器中元素的操作類型:multiset<Sales_data, decltype(compareIsbn)*> bookstore(&compareIsbn);

關聯容器額外的類型別名:key_type、mapped_type、value_type

添加元素:insert、emplace

訪問元素:find(k)、count(k)、low_bound(k)、upper_bound(k)、equal_range(k)

無序容器:組織元素不是通過使用比較運算符,而是使用一個哈希函數和關鍵字類型的==運算符

術語表:hash、哈希函數、嚴格弱序

 

第十二章 動態內存

標准庫定義了兩個智能指針類型來管理動態分配的對象

每個程序擁有一個內存池,我們稱之為自由空間(或堆),程序用堆來存儲動態分配的對象

動態分配的對象:在程序運行時分配的對象,其生存期由程序來控制

管理動態內存:new在動態內存中為對象分配空間並返回一個指向該對象的指針(我們可以選擇對對象進行初始化);delete接受一個動態對象的指針,銷毀該對象並釋放與之關聯的內存

使用動態內存易出現的問題:內存泄漏、產生引用非法內存的指針

為了更容易地使用動態內存,新的標准庫提供了兩種智能指針類型來管理動態對象

智能指針:負責自動釋放所指向的對象

shared_ptr類:初始化/賦值、支持的操作

make_shared函數:創建一個動態對象並初始化,返回指向該動態對象的shared_ptr

make_shared用其參數來構造給定類型的對象,如調用make_shared<string>時傳遞的參數必須與string的某個構造函數相匹配

shared_ptr的析構函數會遞減它指向的對象的引用計數,如果引用計數變為0,則還會銷毀對象並釋放它占用的內存

即如果有n個shared_ptr指向同一個對象,那該對象的引用計數就是n,於是每銷毀一個shared_ptr時,引用計數就減1

幾種遞增/遞減引用計數的情況:譬如返回一個智能指針將遞增計數,因為在調用點會有一個shared_ptr保存返回來的智能指針

程序使用動態內存的一個原因:程序需要在多個對象間共享數據

Blob類:Blob對象的不同拷貝之間共享相同的元素,實現代碼

直接管理內存:new無法為其動態分配的對象命名,值初始化與默認初始化的區別

new分配的對象都是默認初始化的

通過內置指針管理的動態對象的生存期:直到被顯式釋放之前,局部指針變量離開作用域會被銷毀

delete之后重置指針值:防止空懸指針

shared_ptr與new結合使用:將一個智能指針綁定到一個用new動態分配的內存上,即用new返回的指針來初始化智能指針

用來初始化智能指針的普通指針:默認是指向動態內存的,如果不是,則必須提供自己的操作來替代delete

不要混用智能指針和內置指針:智能指針的特性只在智能指針之間操作才會有效

unique_str類:綁定到一個new返回的指針上,不支持普通的拷貝和賦值操作

不能拷貝unique_str的例外:可以拷貝和賦值一個將要銷毀的unique_ptr

向unique_ptr傳遞刪除器:默認使用delete釋放它指向的對象,可重載一個刪除器;類似於重載關聯容器的比較操作

weak_ptr類:不可控制所指向對象生存期的智能指針,指向由一個shared_ptr管理的對象

StrBlobPtr類:相當於指向StrBlob類的指針,可訪問修改vector<string>的元素,實例代碼

動態數組:一次性為很多元素分配內存

allocator類:允許我們將分配和初始化分離,而new將內存分配和對象構造組合在了一起

allocator支持的操作:分配/釋放內存、構造/銷毀對象

標准庫為allocator類定義了兩個伴隨算法:在分配的原始內存中創建對象

文本查詢程序:標准庫相關內容學習的總結

術語表:釋放器、定位new、引用計數

 

第三部分 類設計者的工具

第十三章 拷貝控制

類對象的幾個操作:拷貝、移動、賦值、銷毀

五種特殊函數:拷貝構造函數、拷貝賦值運算符、移動構造函數、移動賦值函數、析構函數

通過定義拷貝控制成員:使類的行為看起來像一個值,或像一個指針

行為像值的類:對於類管理的資源,每個對象都擁有一份自己的拷貝

行為像指針的類:多個對象共同管理相同的資源

拷貝並交換:將左側運算對象與右側運算對象的一個副本進行交換,而返回左側對象,常用於定義賦值運算符

拷貝控制示例:練習應用拷貝控制成員

動態內存管理類:該類在運行時分配可變大小的內存空間,自己進行內存分配,如標准庫中的vector類

StrVec類:vector類的簡化版本,練習如何實現動態內存管理類,主要知識點為allocator類的應用

對象移動:移動而非拷貝對象,類似IO類、unique_ptr這樣的類的對象不能拷貝但可以移動

右值引用:必須綁定到右值的引用

標准庫move函數:可顯式地將一個左值轉換為對應的右值引用類型,即可以通過它來獲得綁定到左值上的右值引用

移動構造/賦值函數:直接接管目標對象的資源,而不需要拷貝

挑選移動還是拷貝函數:根據傳遞的實參,如實參是右值,當然選移動

noexcept:聲明函數不會拋出異常

引用限定符:&和&&放在參數列表后面,分別指出this可以指向一個左值(即只能向可修改的左值賦值)或右值

術語表:拷貝初始化、刪除的函數、move、移動迭代器

 

第十四章 重載運算符與類型轉換

不可重載的運算符::: 、.* 、. 、?:

作為成員還是非成員:非成員的可以是算術、相等性、關系和位運算,成員的有=/[]/()/->/+=/++/解引用

重載輸入運算符>>:需要檢查讀取操作是否成功,即必須處理輸入可能失敗的情況

定義前置/后置版本的遞增/減運算符:為了區別開來,會使后置版本多一個形式上的整型形參

函數調用運算符:可以像使用函數一樣使用該類的對象,與可調用對象的共性,funtion類型

類類型轉換:類型轉換運算符及使用它應避免二義性

術語表:調用形式、類類型轉換、類型轉換運算符、函數表、函數對象

 

第十五章 面向對象程序設計

面向對象程序設計基於三個基本概念:數據抽象、繼承和動態綁定

OOP概述:數據抽象(將類的接口與實現分離)、繼承(定義相似的類型並對其相似關系建模)、動態綁定(在一定程度上忽略相似類型的區別,而以統一的方式使用它們的對象)

虛函數:某些成員函數,基類希望它的派生類各自定義適合自身的版本

動態綁定(函數調用):使用基類的引用或指針調用一個虛函數時發生動態綁定

派生類可以繼承定義在基類中的成員,但是派生類的成員函數不一定有權訪問從基類繼承而來的成員

派生類對象的組成:一個含有派生類自己定義的非static成員的子對象 + 一個與該派生類繼承的基類對應的子對象(如果由多個基類,此子對象也有多個)

派生類向基類的類型轉換:因為派生類對象中含有與其基類對應的組成部分,所以能把派生類的對象當成基類對象來使用,而我們也能將基類的引用或指針綁定到派生類對象中的基類部分上;編譯器會隱式地執行派生類到基類的轉換!!但該轉換只對指針或引用類型有效

類型轉換帶來的:可以把派生類對象或派生類對象的引用用在需要基類引用的地方,同樣也可以把派生類對象的指針用在需要基類指針的地方

派生類不能直接初始化其對象中的基類部分:和其他創建了基類對象的代碼一樣,必須使用基類的構造函數來初始化它的基類部分

即每個類控制它自己的成員初始化過程

派生類的作用域嵌套在基類的作用域之內:派生類成員可以像使用本類成員一樣使用基類的成員

防止繼承的發生:在類名之后跟一個關鍵字final

靜態類型&動態類型

抽象基類:含有(或未經覆蓋直接繼承)純虛函數的類,我們不能創建抽象基類的對象

派生類訪問基類的成員:protected成員的特性

三種繼承方式對於訪問控制的影響:派生類對其繼承而來的成員的訪問權限

改變個別成員的可訪問性:使用using聲明來改變派生類繼承的某個名字的訪問級別

繼承中的名字查找:派生類的作用域嵌套在基類中,對象的靜態類型決定了從哪個類開始搜索名字

名字查找先於類型檢查:因為派生類的作用域嵌套在基類中,故其中與基類同名的函數會隱藏基類中的函數,即只要找到此名字的函數就停止向基類搜索

虛析構函數:動態分配繼承體系中的對象,在基類中將析構函數定義成虛函數

繼承與拷貝控制:位於繼承體系中的類進行拷貝控制操作時應注意基類的拷貝控制

繼承的構造函數:派生類可使用using聲明語句繼承基類的構造函數,但不能繼承默認、拷貝和移動構造函數

容器與繼承:使用容器存放繼承體系中的對象

文本查詢程序再探:擴展文本查詢程序,增加更多查詢操作,作為繼承的最后一個例子

術語表:可訪問的、派生類向基類的類型轉換、動態類型、覆蓋、多態性、重構、公有繼承

 

第十六章 模板與泛型編程

模板是泛型編程的基礎

模板的編寫格式:函數/類模板、類模板的友元、成員模板

模板實參的深入:類型轉換、顯式實參

重載與模板:特例化版本優先、非函數模板優先

引用折疊和右值引用參數:函數參數是右值引用

可變參數模板:sizeof...運算符、參數包、包擴展

模板特例化:模板的一個特例化版本,並非重載模板

術語表:模板參數、模板參數列表、類型參數、實例化、成員模板、參數包、函數參數包、類型轉換

 

第四部分 高級主題

第十七章 標准庫特殊設施

介紹四個具有特殊目的的標准庫設施,以及IO庫中某些不常用的部分

tuple類型:類似pair,但包含的類型更多

biset類型:相對位運算來說,處理二進制數更容易

正則表達式:很好的描述字符序列的方法

隨機數:隨機數引擎+分布類型,我們說的隨機數發生器就是指分布對象和引擎對象的組合

IO庫再探:一系列操縱符控制輸入輸出格式、未格式化的輸入/輸出操作允許將一個流當做一個無解釋的字節序列來處理、定位流中位置並隨機訪問

術語表:tupe、biset、regex、cmatch、smatch、未格式化IO、隨機數引擎、隨機數分布、操縱符、種子

 

第十八章 用於大型程序的工具

介紹在設計大型程序時最有用的三個特效,包含異常處理、命名空間和多重繼承

noexcept異常說明:指定某個函數不會拋出異常

noexcept運算符:可與noexcept說明符混合使用

異常說明與指針、虛函數和拷貝控制:函數的異常說明對於使用函數的影響

異常類層次:標准庫異常類構成了一套繼承體系

命名空間:作用域 + using聲明 + using指示 

命名空間中的名字&多個文件:using聲明的作用域+using指示的弊端

重載與命名空間:命名空間對函數的匹配過程的影響

多重繼承:從多個直接基類產生派生類

多重繼承的初始化過程及其拷貝控制

虛繼承:每個派生類最多一次繼承同一個類

先初始化虛基類部分,再構造其他非虛基類

術語表:構造函數順序、文件中的靜態聲明、全局命名空間、命名空間污染、重新拋出

 

第十九章 特殊工具與技術

介紹幾種用於特定類別問題的特殊工具和技術

重載new和delete:自定義內存分配的細節

使用定位new形式構造對象:傳遞一個地址,在一個特定的、預先分配的內存地址上構造對象,而不分配內存

運行時類型識別:typeid運算符 + dynamic_cast運算符

枚舉類型:定義新的類型

類成員指針:數據成員指針 + 成員函數指針

嵌套類:作用域 + 名字查找 + 與外層類的關系

union類型:任意時刻只有一個數據成員有值

局部類:類定義在某個函數內部 + 名字查找

固有的不可移植的特性:為了支持低層編程而定義的,不可移植的特性是指因機器而異的特性,包括位域、volatile限定符和鏈接指示

術語表:匿名union、判別式、RTTI、定位new表達式、枚舉類型、dynamic_cast、鏈接指示

 

附錄

靜態成員 p268

析構函數:銷毀元素,釋放內存

類型別名:typedef int arrT[10]; arrT是一個由10個整型元素組成的數組的別名

與類的對象交互必須使用該類的接口

通過作用域運算符來使用被隱藏的名字

Sales_data類:p240

Screen類:p243

StrBlob類:p405

StrBlobPtr類:p421

文本查詢程序:p430  T13.42

Message類:p461

StrVec類:p465 T13.44

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM