1.Cpu cache 加速

int main()

{

const int row = 10240;

const int col = 10240;

//這裡採用new的形式來在堆上分配,直接宣告matrix[row][col]會有告警,在棧上分配不下

int** matrix = new int*[row];

for (int i = 0; i < row; i++)

{

matrix[i] = new int[col];

for (size_t j = 0; j < col; j++)

{

matrix[i][j] = 1;

}

}

//按行遍歷

CAL_TIME_BEGIN(row)

int sum_row = 0;

for (int r = 0; r < row; r++)

{

for (int c = 0; c < col; c++)

{

sum_row += matrix[r][c];

}

}

CAL_TIME_END(row)

//按列遍歷

CAL_TIME_BEGIN(col)

int sum_col = 0;

for (int c = 0; c < col; c++)

{

for (int r = 0; r < row; r++)

{

sum_col += matrix[r][c];

}

}

CAL_TIME_END(col)

return 0;

}

這麼一段程式碼,按行遍歷和按列遍歷,計算量應該是相同的,都是row*col的數量相加,實際輸出結果按行遍歷用225ms,而按列使用了900ms多。這裡就涉及到到了cpu cache相關的知識,具體說起來很麻煩,不過可以概括為一點就是

上面是兩段

二維陣列

的遍歷方式,一種按行遍歷,另一種是按列遍歷,乍一看您可能認為計算量沒有任何區別,但其

實按行遍歷比按列遍歷速度快的多,這就是CPU Cache 起到了作用,根據

程式區域性性原理

,訪問主存時會把相鄰的部

分資料也載入到Cache 中,下次訪問相鄰資料時Cache 的命中率極高,速度自然也會提升不少。

平時程式設計過程中也可以多利用好程式的時間區域性性和空間區域性性原理,就可以提高CPU Cache 的命中率,提高程式運

行的效率

然後記憶體的失效又涉及到LRU ARC等演算法問題。但是實際寫程式碼裡很少用到,只要知道有這個知識點該能避開很多大坑。

2.shared_ptr, unique_ptr,weak_ptr原始碼

shared_ptr

在複製的時候引用計數+1 ,在移動的時候是不會加的可以看原始碼

複製構造

template

void _Copy_construct_from(const shared_ptr<_Ty2>& _Other) noexcept {

// implement shared_ptr‘s (converting) copy ctor

_Other。_Incref();

_Ptr = _Other。_Ptr;

_Rep = _Other。_Rep;

}

移動構造

template

void _Move_construct_from(_Ptr_base<_Ty2>&& _Right) noexcept {

// implement shared_ptr’s (converting) move ctor and weak_ptr‘s move ctor

_Ptr = _Right。_Ptr;

_Rep = _Right。_Rep;

_Right。_Ptr = nullptr;

_Right。_Rep = nullptr;

}

而std::unique_ptr的話是沒法賦值的

unique_ptr

(const unique_ptr&) = delete;

unique_ptr& operator=(const unique_ptr&) = delete;

只能轉移

std::unique_ptr bbbb = std::make_unique();

std::unique_ptr ccc = std::move(bbbb);

std::weak_ptr 就不看了,也差不多這麼個玩法,只是多了引用計數,防止引起迴圈呼叫的。

3.堆,棧空間的增長(轉)

我們都知道X86系統程序中

堆疊

都向下增長的,那為什麼是向下增長呢?

“這個問題與虛擬地址空間的分配規則有關,每一個可執行C程式,從低地址到高地址依次是:text,data,bss,堆,棧,

環境引數變數

;其中堆和棧之間有很大的地址空間空閒著,在需要分配空間的時候,堆向上漲,棧往下漲。”

這樣設計可以使得堆和棧能夠充分利用空閒的地址空間。如果棧向上漲的話,我們就必須得指定棧和堆的一個嚴格分界線,但這個分界線怎麼確定呢?

平均分

?但是有的程式使用的堆空間比較多,而有的程式使用的棧空間比較多。所以就可能出現這種情況:一個程式因為棧溢位而崩潰的時候,其實它還有大量閒置的堆空間呢,但是我們卻無法使用這些閒置的堆空間。所以呢,最好的辦法就是讓堆和棧一個向上漲,一個向下漲,這樣它們就可以最大程度地共用這塊剩餘的地址空間,達到利用率的最大化!!

呵呵,其實當你明白這個原理的時候,你也會不由地驚歎當時設計計算機的那些科學家驚人的聰明和智慧!!

C++筆記(一)

的棧是向高地址增長,INTEL的8031、8032、8048、8051系列使用向高地址增長的堆疊;但同樣是INTEL,在x86系列中全部使用向低地址增長的堆疊。其他公司的CPU中除ARM的結構提供向高地址增長的堆疊選項外,多數都是使用向低地址增長的堆疊。

在沒有MMU的時代,為了最大的利用記憶體空間,堆和棧被設計為從兩端相向生長。那麼哪一個向上,哪一個向下呢?

人們對資料訪問是習慣於向上的,比如你在堆中new一個數組,是習慣於把低元素放到低地址,把高位放到高地址,所以堆向上生長比較符合習慣。而棧則對方向不敏感,一般對棧的操作只有PUSH和pop,無所謂向上向下,所以就把堆放在了低端,把棧放在了高階。MMU出來後就無所謂了,只不過也沒必要改了

4。仿函式

仿函式實際上使用的是仿函式類的物件。

差不多就是過載了一下類的 ()運算子,呼叫的時候看起來像函式,算是個語法糖吧

程式碼是複製的,自己跑了下。

#include

using namespace std;

class A{

public:

int a;

};

template class Less

{

public:

bool operator()(const T &t1,const T &t2)

{

return (t1

}

};

template class Bigger

{

public:

bool operator()(const T &t1,const T &t2){

return(t1>t2);

}

};

template void PrintValue(const T &t1,const T &t2,T1 cmp)

{

if(cmp(t1,t2)) //cmp 是 PrintValue(1,7,Bigger()); 中Bigger 一個物件。cmp 的使用卻像一個函式。所以有仿函式一說。

cout<

else

cout<

}

int main(int argc,char*argv[]){

Bigger a;

PrintValue(1,7,a);

//PrintValue(4。5,8。6,Less()); 顯式呼叫預設建構函式。

Bigger b=Bigger();

A g=A();

cout<

//cout<

5.科學上網外掛

switchomega

6.source tree windows

source tree 很好用,但是資料夾上沒了圖示,那就裝一個tortisegit好了,兩個工具一起用,那就資料夾有圖示了

source tree開啟大檔案比對的時候超級卡,可以設定不進行比對,然後自己想辦法比對就是了。

工具->選項

C++筆記(一)

7.結構體賦值 C++17以上才有的功能

struct Person p4 = {。heigth=1。77, 。name=“wangwu”, 。age=33};

8。C++ 匿名空間

這個空間匿名了,在呼叫的時候可能就看不到namespace了

9。 as 設定代理後去不掉

Android studio 設定了一下代理,然後在介面上設定無效,一直有代理,原因是全域性的檔案

gradle。properties

,開啟這個檔案可以看到你之前配置的代理資訊還在,直接刪除掉吧。

這個檔案在目錄裡找,或者用everything 搜一下看看就知道了。

10。GO 語言

go mod indirect 這個表示這個包不用當前專案裡用到但是在別的專案裡用到,表示

間接依賴