日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程语言 > c/c++ >内容正文

c/c++

2020 我的C++的学习之路 第九章 内存模型与名称空间

發(fā)布時(shí)間:2025/3/20 c/c++ 17 豆豆
生活随笔 收集整理的這篇文章主要介紹了 2020 我的C++的学习之路 第九章 内存模型与名称空间 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

以C++ Primer Plus為參考書籍,自身歸納知識(shí)點(diǎn),加深記憶。

內(nèi)存模型與名稱空間

  • 存儲(chǔ)持續(xù)性
    • 作用域與鏈接
    • 自動(dòng)存儲(chǔ)持續(xù)性
    • 靜態(tài)持續(xù)變量
      • 靜態(tài)持續(xù)性、外部鏈接性
      • 靜態(tài)持續(xù)性、內(nèi)部鏈接性
      • 靜態(tài)持續(xù)性、無(wú)鏈接性
    • 說(shuō)明符和限定符
      • 存儲(chǔ)說(shuō)明符
      • cv-限定符
    • 定位new運(yùn)算符
  • 名稱空間
    • using聲明與using編譯指令
    • 名稱空間的其他特性
    • 未命名的名稱空間

存儲(chǔ)持續(xù)性

①自動(dòng)存儲(chǔ)持續(xù)性:在函數(shù)定義中聲明的變量的存儲(chǔ)持續(xù)性為自動(dòng),在程序開(kāi)始執(zhí)行所屬的函數(shù)或代碼塊 時(shí)被創(chuàng)建,在執(zhí)行完函數(shù)或代碼塊時(shí),它們的內(nèi)存被釋放。

②靜態(tài)存儲(chǔ)持續(xù)性:在函數(shù)定義外定義的變量和使用關(guān)鍵字static定義的變量的存儲(chǔ)性為靜態(tài),在程序運(yùn)行的整個(gè)運(yùn)行過(guò)程都存在

③動(dòng)態(tài)存儲(chǔ)持續(xù)性:用new運(yùn)算符分配的內(nèi)存一直都在,直到delete或者程序結(jié)束為止,這種存儲(chǔ)持續(xù)性為動(dòng)態(tài),有時(shí)被稱為自由存儲(chǔ)或者堆

④線程存儲(chǔ)持續(xù)性(C++11):多核處理器中,讓程序能狗將計(jì)算放在可并行處理的不同線程中,如果變量是使用關(guān)鍵字 thread_local聲明的,則生命周期與所屬的線程一樣長(zhǎng)

作用域與鏈接

作用域(scope)描述了名稱在文件的多大范圍內(nèi)可見(jiàn)
鏈接性(linkage)描述了名稱如何在不同單元間共享

自動(dòng)存儲(chǔ)持續(xù)性

①在默認(rèn)情況下,函數(shù)中聲明的函數(shù)參數(shù)和變量的存儲(chǔ)持續(xù)性都為自動(dòng),局部作用域,無(wú)鏈接性。

int main() {int n = 5;{int n =10;cout<<n;//n=10}cout<<n;//n=10 }

兩個(gè)n都是局部變量,各自在局部作用域中作用,內(nèi)部的n=10會(huì)隱藏外部n=5的定義,當(dāng)程序離開(kāi)內(nèi)部代碼塊時(shí),原來(lái)的定義又重新可見(jiàn)。

②自動(dòng)變量被存儲(chǔ)在棧中,后進(jìn)先出,即最后加入到棧中的變量首先被彈出。

③atuo關(guān)鍵字在C語(yǔ)言中用于顯式地指出變量為自動(dòng)存儲(chǔ),但在C++11標(biāo)準(zhǔn)下,atuo改為自動(dòng)類型推斷

④register關(guān)鍵字在C語(yǔ)言中用于寄存器存儲(chǔ)自動(dòng)變量以提高訪問(wèn)速度,但在C++11標(biāo)準(zhǔn)下,register用于顯式指出變量為自動(dòng)存儲(chǔ)

靜態(tài)持續(xù)變量

靜態(tài)存儲(chǔ)持續(xù)性變量有三種鏈接性:外部鏈接(可跨文件訪問(wèn)),內(nèi)部鏈接(當(dāng)前文件訪問(wèn)),無(wú)鏈接(當(dāng)前函數(shù)或代碼塊訪問(wèn)),這三種鏈接性在程序執(zhí)行期間存在,編譯器將分配固定的內(nèi)存存儲(chǔ)所有的靜態(tài)變量,而不是棧。倘若沒(méi)有顯式的初始化靜態(tài)變量,則編譯器默認(rèn)為0。

//a.cpp int global = 100;//靜態(tài)全局變量,外部鏈接的靜態(tài)變量 static int n = 90;//內(nèi)部鏈接的靜態(tài)變量 int main() {... }void fun1() {static int cnt = 5;//無(wú)鏈接的靜態(tài)變量int sa = 0;//自動(dòng)變量 }

外部鏈接性靜態(tài)持續(xù)變量:必須在代碼塊外面聲明;
內(nèi)部鏈接性靜態(tài)持續(xù)變量:必須在代碼塊外面聲明,并用static限定
無(wú)鏈接性靜態(tài)持續(xù)變量:必須在代碼塊內(nèi)部聲明,并用static限定

靜態(tài)持續(xù)性、外部鏈接性

倘若存在另外一個(gè)文件b.cpp使用a.cpp中的global變量,那么需要在b.cpp中使用關(guān)鍵字extern且不對(duì)global進(jìn)行定義。

// external.cpp -- external variable // compile with support.cpp #include <iostream> // external variable double warming = 0.3; // warming defined// function prototypes void update(double dt); void local();int main() // uses global variable {using namespace std;cout << "Global warming is " << warming << " degrees.\n";//0.3update(0.1); // call function to change warming//0.4cout << "Global warming is " << warming << " degrees.\n";//0.4local(); // call function with local warming//0.8 0.4cout << "Global warming is " << warming << " degrees.\n";//0.4// cin.get();return 0; } // support.cpp -- use external variable // compile with external.cpp #include <iostream> extern double warming; // use warming from another file// function prototypes void update(double dt); void local();using std::cout; void update(double dt) // modifies global variable {extern double warming; // optional redeclaration,此處可以省略聲明,因?yàn)樯喜柯暶鬟^(guò)一次warming += dt; // uses global warmingcout << "Updating global warming to " << warming;cout << " degrees.\n"; }void local() // uses local variable {double warming = 0.8; // new variable hides external onecout << "Local warming = " << warming << " degrees.\n";// Access global variable with the// scope resolution operatorcout << "But global warming = " << ::warming;//::作用域解析運(yùn)算符,放在變量名前面會(huì)使用全局版本,故此處應(yīng)是0.4cout << " degrees.\n"; }

靜態(tài)持續(xù)性、內(nèi)部鏈接性

// twofile1.cpp -- variables with external and internal linkage #include <iostream> // to be compiled with two file2.cpp int tom = 3; // external variable definition int dick = 30; // external variable definition static int harry = 300; // static, internal linkage // function prototype void remote_access();int main() {using namespace std;cout << "main() reports the following addresses:\n";cout << &tom << " = &tom, " << &dick << " = &dick, ";cout << &harry << " = &harry\n";remote_access();// cin.get();return 0; } // twofile2.cpp -- variables with internal and external linkage #include <iostream> extern int tom; // tom defined elsewhere static int dick = 10; // overrides external dick//覆蓋上部的dick變量,此處為靜態(tài)內(nèi)部鏈接變量 int harry = 200; // external variable definition,// no conflict with twofile1 harryvoid remote_access() {using namespace std;cout << "remote_access() reports the following addresses:\n";cout << &tom << " = &tom, " << &dick << " = &dick, ";cout << &harry << " = &harry\n"; }

靜態(tài)持續(xù)性、無(wú)鏈接性

無(wú)鏈接性的靜態(tài)變量用關(guān)鍵詞static在代碼塊中聲明,即使該代碼塊不處于活動(dòng)狀態(tài)時(shí),該變量一直存在,并且只在啟動(dòng)一次時(shí)進(jìn)行初始化,以后再調(diào)用函數(shù)時(shí),該變量不會(huì)被初始化

// static.cpp -- using a static local variable #include <iostream> // constants const int ArSize = 10;// function prototype void strcount(const char * str);int main() {using namespace std;char input[ArSize];char next;cout << "Enter a line:\n";cin.get(input, ArSize);while (cin){cin.get(next);while (next != '\n') // string didn't fit!cin.get(next); // dispose of remainderstrcount(input);cout << "Enter next line (empty line to quit):\n";cin.get(input, ArSize);}cout << "Bye\n"; // code to keep window open for MSVC++ /* cin.clear();while (cin.get() != '\n')continue;cin.get(); */return 0; }void strcount(const char * str) {using namespace std;static int total = 0; // static local variableint count = 0; // automatic local variablecout << "\"" << str <<"\" contains ";while (*str++) // go to end of stringcount++;total += count;cout << count << " characters\n";cout << total << " characters total\n"; }

count每次調(diào)用都會(huì)被初始化為0,而total僅在第一次調(diào)用才會(huì)被初始化為0,每次調(diào)用后都會(huì)被存儲(chǔ),從而達(dá)到計(jì)數(shù)累加的效果。

說(shuō)明符和限定符

存儲(chǔ)說(shuō)明符

①auto(C++11不再是說(shuō)明符)
②register
③static
④extern
⑤thread_local
⑥mutable(即使結(jié)構(gòu)或類變量為const,但用mutable可以使其聲明的成員被修改)
同一個(gè)聲明中不能使用多個(gè)說(shuō)明符,但thread_local除外,可與static或extern結(jié)合使用

cv-限定符

①const
②volatile
關(guān)鍵詞volatile表明,即使程序代碼沒(méi)有對(duì)內(nèi)存單元進(jìn)行修改,其值也可能會(huì)發(fā)生變化。

在C++中,倘若對(duì)全局變量(靜態(tài)持續(xù)性,外部鏈接)加以const限定,可將該變量的鏈接性改為內(nèi)部鏈接性,也就是說(shuō)在C++中,全局變量const限定相當(dāng)于static存儲(chǔ)說(shuō)明。

定位new運(yùn)算符

通常new負(fù)責(zé)在堆中找到一個(gè)滿足要求的內(nèi)存塊,而定位new運(yùn)算符則可以指定要使用的位置

double *ptr = new double[5];//動(dòng)態(tài)分配內(nèi)存 struct chaff {char drss[20];int slag; }char buffer[500]; chaff *pch; pch = new (buffer)chaff;//將結(jié)構(gòu)chaff放入指定的buffer內(nèi)存當(dāng)中,并分配合適的內(nèi)存大小 // newplace.cpp -- using placement new #include <iostream> #include <new> // for placement new const int BUF = 512; const int N = 5; char buffer[BUF]; // chunk of memory int main() {using namespace std;double *pd1, *pd2;int i;cout << "Calling new and placement new:\n";pd1 = new double[N]; // use heappd2 = new (buffer) double[N]; // use buffer arrayfor (i = 0; i < N; i++)pd2[i] = pd1[i] = 1000 + 20.0 * i;cout << "Memory addresses:\n" << " heap: " << pd1<< " static: " << (void *) buffer <<endl;cout << "Memory contents:\n";for (i = 0; i < N; i++){cout << pd1[i] << " at " << &pd1[i] << "; ";cout << pd2[i] << " at " << &pd2[i] << endl;}cout << "\nCalling new and placement new a second time:\n";double *pd3, *pd4;pd3= new double[N]; // find new addresspd4 = new (buffer) double[N]; // overwrite old datafor (i = 0; i < N; i++)pd4[i] = pd3[i] = 1000 + 40.0 * i;cout << "Memory contents:\n";for (i = 0; i < N; i++){cout << pd3[i] << " at " << &pd3[i] << "; ";//pd[3]的地址與pa[1]的地址不一樣,重新分配了一塊新的地址cout << pd4[i] << " at " << &pd4[i] << endl;//pd[4]的地址與pa[2]的地址一樣}cout << "\nCalling new and placement new a third time:\n";delete [] pd1;pd1= new double[N];pd2 = new (buffer + N * sizeof(double)) double[N]; for (i = 0; i < N; i++)pd2[i] = pd1[i] = 1000 + 60.0 * i;cout << "Memory contents:\n";for (i = 0; i < N; i++){cout << pd1[i] << " at " << &pd1[i] << "; ";cout << pd2[i] << " at " << &pd2[i] << endl;}delete [] pd1;//buffer指定的是靜態(tài)內(nèi)存,而delete只能用于指向的堆內(nèi)存,因此不能用deletedelete [] pd3;// cin.get();return 0; }

名稱空間

名稱空間可以是全局的,也可以是位于另一個(gè)名稱空間中,但不能處于代碼塊中,因此在默認(rèn)情況下,在名稱空間中聲明的名稱的鏈接性是外部的。

namespace Jack {double pail;void fetch();int pal;struct Well{...}; } namespace Jill {double bucket(double n){...};double fetch;int pal;struct Hill{...} }

任何名稱空間中的名稱都不會(huì)與其他名稱空間中的名稱發(fā)生沖突,因此Jack中的fetch與Jill中的fetch共存,Jill中的Hill可以與外部的Hill共存。
名稱空間是開(kāi)放的,可以把名稱加入到已有的名稱空間中

namespace Jill {char * goose(const char*);//加入上述的Jill中 }

利用作用域解析運(yùn)算符::來(lái)訪問(wèn)名稱空間中的名稱,使用名稱空間限定該名稱:

Jack::pail = 12.34;//賦值 Jill::Hill mole;//結(jié)構(gòu) Jack::fetch();//函數(shù)調(diào)用

在名稱空間中聲明的函數(shù)名的作用域?yàn)檎麄€(gè)名稱空間,因此聲明和定義必須位于同一個(gè)名稱空間中

using聲明與using編譯指令

using聲明:

using Jill::fetch;

using編譯指令:

using namespace Jill;

using聲明只是讓名稱空間中的一個(gè)名稱可用;using編譯指令則是可以使用名稱空間中的所有名稱,可以認(rèn)為using編譯指令中包含了所有名稱的using聲明。

名稱空間的其他特性

可以將名稱空間聲明進(jìn)行嵌套:

namespace elements {namespace fire{int flame;...}float water; }

倘若要使用fire內(nèi)部的名稱,則using namespace elements::fire;
另外名稱空間中也可以使用using編譯指令和using聲明:

namespace myth {using Jill::fetch;using namespace elements;using std::cout;using std::cin; }

倘若要訪問(wèn)fetch,因此可以這樣myth::fetch;,也可以Jill::fetch;

未命名的名稱空間

namespace {int count; }

未命名的名稱空間相當(dāng)于提供了內(nèi)部鏈接性的靜態(tài)變量。

總結(jié)

以上是生活随笔為你收集整理的2020 我的C++的学习之路 第九章 内存模型与名称空间的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。