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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > c/c++ >内容正文

c/c++

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

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

以C++ Primer Plus為參考書籍,自身歸納知識點,加深記憶。

內存模型與名稱空間

  • 存儲持續性
    • 作用域與鏈接
    • 自動存儲持續性
    • 靜態持續變量
      • 靜態持續性、外部鏈接性
      • 靜態持續性、內部鏈接性
      • 靜態持續性、無鏈接性
    • 說明符和限定符
      • 存儲說明符
      • cv-限定符
    • 定位new運算符
  • 名稱空間
    • using聲明與using編譯指令
    • 名稱空間的其他特性
    • 未命名的名稱空間

存儲持續性

①自動存儲持續性:在函數定義中聲明的變量的存儲持續性為自動,在程序開始執行所屬的函數或代碼塊 時被創建,在執行完函數或代碼塊時,它們的內存被釋放。

②靜態存儲持續性:在函數定義外定義的變量和使用關鍵字static定義的變量的存儲性為靜態,在程序運行的整個運行過程都存在

③動態存儲持續性:用new運算符分配的內存一直都在,直到delete或者程序結束為止,這種存儲持續性為動態,有時被稱為自由存儲或者堆

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

作用域與鏈接

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

自動存儲持續性

①在默認情況下,函數中聲明的函數參數和變量的存儲持續性都為自動,局部作用域,無鏈接性。

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

兩個n都是局部變量,各自在局部作用域中作用,內部的n=10會隱藏外部n=5的定義,當程序離開內部代碼塊時,原來的定義又重新可見。

②自動變量被存儲在棧中,后進先出,即最后加入到棧中的變量首先被彈出。

③atuo關鍵字在C語言中用于顯式地指出變量為自動存儲,但在C++11標準下,atuo改為自動類型推斷

④register關鍵字在C語言中用于寄存器存儲自動變量以提高訪問速度,但在C++11標準下,register用于顯式指出變量為自動存儲

靜態持續變量

靜態存儲持續性變量有三種鏈接性:外部鏈接(可跨文件訪問),內部鏈接(當前文件訪問),無鏈接(當前函數或代碼塊訪問),這三種鏈接性在程序執行期間存在,編譯器將分配固定的內存存儲所有的靜態變量,而不是棧。倘若沒有顯式的初始化靜態變量,則編譯器默認為0。

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

外部鏈接性靜態持續變量:必須在代碼塊外面聲明;
內部鏈接性靜態持續變量:必須在代碼塊外面聲明,并用static限定
無鏈接性靜態持續變量:必須在代碼塊內部聲明,并用static限定

靜態持續性、外部鏈接性

倘若存在另外一個文件b.cpp使用a.cpp中的global變量,那么需要在b.cpp中使用關鍵字extern且不對global進行定義。

// 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,此處可以省略聲明,因為上部聲明過一次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;//::作用域解析運算符,放在變量名前面會使用全局版本,故此處應是0.4cout << " degrees.\n"; }

靜態持續性、內部鏈接性

// 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變量,此處為靜態內部鏈接變量 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"; }

靜態持續性、無鏈接性

無鏈接性的靜態變量用關鍵詞static在代碼塊中聲明,即使該代碼塊不處于活動狀態時,該變量一直存在,并且只在啟動一次時進行初始化,以后再調用函數時,該變量不會被初始化

// 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每次調用都會被初始化為0,而total僅在第一次調用才會被初始化為0,每次調用后都會被存儲,從而達到計數累加的效果。

說明符和限定符

存儲說明符

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

cv-限定符

①const
②volatile
關鍵詞volatile表明,即使程序代碼沒有對內存單元進行修改,其值也可能會發生變化。

在C++中,倘若對全局變量(靜態持續性,外部鏈接)加以const限定,可將該變量的鏈接性改為內部鏈接性,也就是說在C++中,全局變量const限定相當于static存儲說明。

定位new運算符

通常new負責在堆中找到一個滿足要求的內存塊,而定位new運算符則可以指定要使用的位置

double *ptr = new double[5];//動態分配內存 struct chaff {char drss[20];int slag; }char buffer[500]; chaff *pch; pch = new (buffer)chaff;//將結構chaff放入指定的buffer內存當中,并分配合適的內存大小 // 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指定的是靜態內存,而delete只能用于指向的堆內存,因此不能用deletedelete [] pd3;// cin.get();return 0; }

名稱空間

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

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

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

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

利用作用域解析運算符::來訪問名稱空間中的名稱,使用名稱空間限定該名稱:

Jack::pail = 12.34;//賦值 Jill::Hill mole;//結構 Jack::fetch();//函數調用

在名稱空間中聲明的函數名的作用域為整個名稱空間,因此聲明和定義必須位于同一個名稱空間中

using聲明與using編譯指令

using聲明:

using Jill::fetch;

using編譯指令:

using namespace Jill;

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

名稱空間的其他特性

可以將名稱空間聲明進行嵌套:

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

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

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

倘若要訪問fetch,因此可以這樣myth::fetch;,也可以Jill::fetch;

未命名的名稱空間

namespace {int count; }

未命名的名稱空間相當于提供了內部鏈接性的靜態變量。

總結

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

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。