c 日常雜記

2021-10-03 23:21:51 字數 4315 閱讀 1721

在類中將成員函式修飾為const表明在該函式體內,不能修改物件的資料成員而且不能呼叫非const函式。為什麼不能呼叫非const函式?因為非const函式可能修改資料成員,const成員函式是不能修改資料成員的,所以在const成員函式內只能呼叫const函式。

1.客戶端

傳送http請求時傳送請求頭rnge:bytes=x-x  表示需要請求的範圍。

2.伺服器端

返回http碼206。(非斷點傳續返回200)

返回頭有如下:

accept-ranges:bytes--表示伺服器端支援斷點續傳

last-modified--也是標識伺服器端資源最後一次改變的時間。

content-ranges:bytes x-x--返回的範圍。

基類指標可以指向派生類的物件(多型性),如果刪除該指標delete p;就會呼叫該指標指向的派生類析構函式,而派生類的析構函式又自動呼叫基類的析構函式,這樣整個派生類的物件完全被釋放。如果析構函式不被宣告成虛函式,則編譯器實施靜態繫結,在刪除基類指標時,只會呼叫基類的析構函式而不呼叫派生類析構函式,這樣就會造成派生類物件析構不完全。所以,將析構函式宣告為虛函式是十分必要的。

一、引入背景

使用 c++ 的指標可以動態開闢儲存空間,但若在使用完畢後忘記釋放(或在釋放之前,程式 throw 出錯誤,導致沒有釋放),導致該記憶體單元一直被佔據直到程式結束,即發生了所謂的記憶體洩漏

【注】記憶體洩漏是指堆記憶體的洩漏。堆,就是那些由 new 分配的記憶體塊。

因此智慧型指標的作用就是為了保證使用堆上物件的時候,物件一定會被釋放,但只能釋放一次,並且釋放後指向該物件的指標應該馬上歸 0

二、c++11 以前的智慧型指標

auto_ptr,指向乙個動態分配的物件指標,它的析構函式用於刪除所指物件的空間,以此達到對物件生存期的控制。

已被棄用,原因是:

函式物件也叫函式符,函式符是可以以函式方式與()結合使用的任意物件。這包括函式名、指向函式的指標和過載了()運算子的類物件

上面這句話的意思是指:函式名、指向函式的指標和過載了括號運算子的類物件與括號結合,從而以函式方式實現某種功能。

有2個原因:

函式物件可以有自己的狀態,即利用它的成員變數來記錄狀態,這樣可以實現一些複雜的功能。

而函式沒有辦法記錄狀態,除非借助於全域性變數。

利用內部狀態可以實現一些複雜的功能,比如,乙個函式物件在多次的呼叫中可以共享這個狀態。

不過需要注意一點,在stl中都是傳值的,所以函式物件也是作為乙個值而被拷貝傳入的;假如函式物件的內部狀態在函式物件被呼叫時會發生改變,則很可能因為每次傳入給呼叫者時,函式物件的內部狀態都會被初始化而導致錯誤(見參考文獻2中的例子)。所以,函式物件的使用者的行為最好不要依賴於函式物件的內部狀態。當然,若函式物件的內部狀態根本不會改變,那即使依賴也沒有問題。

stl中不少容器的模板引數都是函式物件,而不是函式指標,因此我們需要使用函式物件。

例子有上面的 unordered_map 的模板引數,又比如,set的模板引數,priority_queue 的模板引數,等等。

那麼,為什麼stl中要使用函式物件呢?為了元件技術中的可適配性(adapability),即將某些修飾條件加諸其上而改變狀態。

在侯捷的《stl原始碼剖析》的1.9.6節和第8章對此有所闡述。

總結:類成員函式指標與普通函式指標不是一碼事。前者要用 .* 與 ->* 運算子來使用,而後者可以用 * 運算子(稱為"解引用"dereference,或稱"間址"indirection)。普通函式指標實際上儲存的是函式體的開始位址,因此也稱"**指標",以區別於 c/c++ 最常用的資料指標。而類成員函式指標就不僅僅是類成員函式的記憶體起始位址,還需要能解決因為 c++ 的多重繼承、虛繼承而帶來的類例項位址的調整問題,所以類成員函式指標在呼叫的時候一定要傳入類例項物件。

#define conn(x,y) x##y

#define tochar(x) #@x

#define tostring(x) #x

(1)x##y表示什麼?表示x連線y,舉例說:

int n = conn(123,456); /* 結果就是n=123456;*/

char* str = conn("asdf", "adf"); /*結果就是 str = "asdfadf";*/

(2)再來看#@x,其實就是給x加上單引號,結果返回是乙個const char。舉例說:

char a = tochar(1);結果就是a='1';

做個越界試驗char a = tochar(123);結果就錯了;

但是如果你的引數超過四個字元,編譯器就給給你報錯了!

error c2015: too many characters in constant   :p

(3)最後看看#x,估計你也明白了,他是給x加雙引號

char* str = tostring(123132);就成了str="123132";

因為在編譯時模板並不能生成真正的二進位制**,而是在編譯呼叫模板類或函式的cpp檔案時才會去找對應的模板宣告和實現,在這種情況下編譯器是不知道實現模板類或函式的cpp檔案的存在,所以它只能找到模板類或函式的宣告而找不到實現,而只好建立乙個符號寄希望於鏈結程式找位址。但模板類或函式的實現並不能被編譯成二進位制**,結果鏈結程式找不到位址只好報錯了。

《c++程式設計思想》第15章(第300頁)說明了原因:

模板定義很特殊。由template<…>處理的任何東西都意味著編譯器在當時不為它分配儲存空間,它一直處於等待狀態直到被乙個模板例項告知。在編譯器和聯結器的某一處,有一機制能去掉指定模板的多重定義。所以為了容易使用,幾乎總是在標頭檔案中放置全部的模板宣告和定義。

#include #include #include #include templateclass tp

friend std::ostream& operator<<(std::ostream& x,const tp& a)

friend std::ofstream& operator<<(std::ofstream& x, tp& a)

int m;

char* str;

};

拷貝建構函式的形參是乙個左值引用,而移動建構函式的形參是乙個右值引用

拷貝建構函式完成的是整個物件或變數的拷貝,而移動建構函式是生成乙個指標指向源物件或變數的位址,接管源物件的記憶體,相對於大量資料的拷貝節省時間和記憶體空間。

全域性變數、全域性靜態變數、區域性靜態變數會被釋放,其它的物件不會被析構,程式裡的指標如果不手動呼叫delete都不會呼叫析構;

#include "iostream"

using namespace std;

class ctest

; inline virtual void test()

inline virtual void test2()

templatevoid mymethod( t myarr )

多型就是多種形態,c++的多型分為靜態多型與動態多型。

靜態多型就是過載,因為在編譯期決議確定,所以稱為靜態多型。在編譯時就可以確定函式位址。

動態多型就是通過繼承重寫基類的虛函式實現的多型,因為實在執行時決議確定,所以稱為動態多型。執行時在虛函式表中尋找呼叫函式的位址。

c++多型虛函式表詳解(多重繼承、多繼承情況)_青城山小和尚-csdn部落格_c++多重繼承有幾個虛函式表

原理:物件淺拷貝,實現對引用計數(同一塊記憶體)的讀寫

templateclass smartptr

smartptr(const smartptr& sp)

~smartptr()

void operator=(const smartptr& sp)

t* get()

t& operator*()

t* operator->()

unsigned int count()

void clear()

private:

unsigned int* refcount;

t* ptr;

};

int main()

{ int * pw = new int(9);

smartptrpw1(pw);

smartptrpw2(pw1);

{smartptrpw3 = pw2;

smartptrpw4 = pw2;

cout<

日常雜記 6

1 避免模擬器編譯 方法 define real device target iphone simulator 0 target os iphone 1 if real device nslog ezopensdk init success d success endif 2 ifdef debug...

c 學習雜記

概念 物件 object 類 class 物件導向 由類組成 是以介面形式存在 易於移植 可以將每乙個變數都看作是物件 每一種資料型別都可以看做是類 類中分為 public protected private 公有 保護 私有 變數 公有變數 任何人都可以訪問 保護變數 自己與自己派生 繼承的都可以...

C語言 雜記

1 常量溢位 u16 adc temp 0 應為 u32 adc temp 0 for i 0 i 100 i adc temp 100 1.2 資料範圍溢位 將乙個數拆分為n個隨機數 for i 0 i 200 i break 可更正為 for i 0 i 200 i else 小於或等於0xff...