c++之引用及記憶體分割槽模型
記憶體分割槽模型
c++程式執行時,將記憶體大放行劃分為4個區域
程式碼區:存放函式體的二進位制碼,由作業系統進行管理的
全域性區:存放全域性變數和靜態變數以及常量
棧區:由編譯器自動分配釋放,存放函式的引數值、區域性變數等
堆區:由程式設計師分配和釋放,若程式設計師不釋放,程式結束時由作業系統收回
在程式執行前
在程式編譯後,生成了exe可執行程式,未執行該程式前分為兩個區域
程式碼區:存放CPU執行的機器指令
特點:
程式碼區是共享的,共享的目的是對於頻繁被執行的程式,只需在記憶體中有一份程式碼即可
程式碼區是隻讀的,使其只讀的原因時防止程式意外的修改了它的指令
全域性區:全域性變數,靜態變數,常量(字串常量,全域性常量(用const修飾的全域性變數))
特點:
只要是用區域性修飾的(區域性變數、區域性常量)都不在全域性區
該區域的資料在程式結束後由作業系統釋放
程式執行後
棧區:由編譯器自動分配釋放,存放函式的引數值,區域性變數等
不要返回區域性變數的地址,因為棧區開闢的資料由編譯器自動釋放
一定要好好看看底下的程式碼,可以幫助理解記憶體分割槽模型!
#include<iostream>
using namespace std;
//棧區資料的注意事項
int* func()
{
int a = 10;//區域性變數 存放在棧區,棧區的資料在函式執行完之後自動釋放,已經被釋放了所以就不能返回
return &a;//返回區域性變數的地址
}
//在堆區開闢資料
int* func1()
{
//利用new關鍵字,可以將資料開闢到堆區
*//p這個指標的本質也是區域性變數,放在棧上,但指標儲存的資料是放在堆區的*
int* p = new int(10);//(初始值)
return p;//返回在堆區開闢空間的地址
}
int main()
{
int* p = func();
cout << *p << endl;//10 第一次可以列印正確是因為編譯器做了保留
cout << *p << endl;//亂碼 第二次就不會保留了
cout << endl;
//堆區 由程式設計師分配釋放,若程式設計師不釋放,程式執行結束時有作業系統回收
int* q = func1();
cout << (int)q << endl;
cout << (int)q << endl;
cout << *q << endl;
cout << *q << endl;
system("pause");
return 0;
}
引用
引用通俗易懂的來講就是給變數起一個別名,別名和原名代表同一塊記憶體,也就是可以通過操作別名間接的對原名操作,一般用在做函式引數。
引用的語法:
資料型別 & 引用名 = 原名
int a =10;
int &b = a;//b就是a的引用
注意事項:
1、引用時必須初始化
2、初始化後就不可更改(不可多次初始化)
引用的本質:
引用在c++內部實現是一個指標常量(指標的指向不可以改變,指標指向的值可以改變),這就是為什麼引用不可多次初始化。
int a = 10;
int &b = a;//等價於int * const b = &a;
b = 20;//等價於*b = 20;
引用的用途:
1、引用做函式引數
在函式傳參是,可以利用引用的技術使形參修飾實參,這可以簡化指標修改實參
//值傳遞
void myswap01(int a, int b)
{
int temp = a;
a = b;
b = temp;
cout << "形參a = " << a << endl;
cout << "形參b = " << b << endl;
}
//地址傳遞
void myswap02(int *a, int *b)
{
int temp = *a;
*a = *b;
*b = temp;
}
//引用傳遞
void myswap03(int &a, int &b)
{
int temp = a;
a = b;
b = temp;
cout << "形參a = " << a << endl;
cout << "形參b = " << b << endl;
}
void test()
{
cout << "值傳遞" << endl;
int a = 10;
int b = 20;
myswap01(a, b);
cout << "實參a = " << a << endl;
cout << "實參b = " << b << endl;
cout << endl;
myswap02(&a, &b);
cout << "實參a = " << a << endl;
cout << "實參b = " << b << endl;
a = 10; b = 20;
myswap03(a, b);//引用傳遞,形參也會修飾實參
cout << "實參a = " << a << endl;
cout << "實參b = " << b << endl;
}
通過測試我們可以發現引用傳遞和地址傳遞的效果是一樣的,但很明顯引用傳遞更簡單,c++推薦使用引用技術。
2、引用做函式返回值
引用是可以作為函式的返回值存在的
注意:不要返回區域性變數引用
用法:函式呼叫作為左值
#include<iostream>
using namespace std;
int& test01()
{
int a = 10;//存放在棧區
return a;
}
int& test02()
{
static int a = 10;//靜態變數,存放再全域性區
return a;
}
int main()
{
int& ref = test01();
cout << "ref = " << ref<<endl;//第一次是對的,是因為編譯器做了保留
cout << "ref = " << ref<<endl;//第一次執行後,a的記憶體已經釋放,所以會輸出亂碼
int& ref1 = test02();
cout << "ref1 = " << ref1 << endl;
cout << "ref1 = " << ref1 << endl;
test02() = 1000;//如果函式的返回值是引用,函式的呼叫可以作為左值(在這裡相當於對a進行賦值)
cout << "ref1 = " << ref1 << endl;
cout << "ref1 = " << ref1 << endl;//ref 是別名,可以訪問a的記憶體
system("pause");
return 0;
}
相關文章
- 請描述C/C++程式的記憶體分割槽?C++記憶體
- 淺析JVM記憶體分割槽JVM記憶體
- [引用分割槽表]Oracle 11g新特性之引用分割槽表Oracle
- Android 分割槽和記憶體監控Android記憶體
- 查詢windows記憶體卡槽及卡槽支援的最大記憶體Windows記憶體
- C++記憶體模型實踐探索C++記憶體模型
- Java記憶體模型FAQ(二) 其他語言,像C++,也有記憶體模型嗎?Java記憶體模型C++
- C++ 引用和指標:記憶體地址、建立方法及應用解析C++指標記憶體
- C++ 解引用與函式基礎:記憶體地址、呼叫方法及宣告C++函式記憶體
- Java記憶體模型及volatileJava記憶體模型
- Java多執行緒-帶你認識Java記憶體模型,記憶體分割槽,從原理剖析Volatile關鍵字Java執行緒記憶體模型
- java虛擬機器執行時記憶體分割槽Java虛擬機記憶體
- jvm:記憶體模型、記憶體分配及GC垃圾回收機制JVM記憶體模型GC
- Oracle分割槽表及分割槽索引Oracle索引
- JAVA的記憶體模型及結構Java記憶體模型
- oracle reference partition引用分割槽(一)Oracle
- Java記憶體模型,垃圾回收機制,常用記憶體命令及工具Java記憶體模型
- 如何查詢分割槽表的分割槽及子分割槽
- 深度解讀《深度探索C++物件模型》之C++物件的記憶體佈局C++物件模型記憶體
- 記憶體模型記憶體模型
- 《深度探索c++記憶體模型》讀書筆記 (二)C++記憶體模型筆記
- 分割槽表及分割槽索引建立示例索引
- Java記憶體模型(MESI、記憶體屏障、volatile和鎖及final記憶體語義)Java記憶體模型
- Volatile之Java記憶體模型概念Java記憶體模型
- 【JVM】JVM系列之記憶體模型(六)JVM記憶體模型
- 全面學習分割槽表及分割槽索引(10)--交換分割槽索引
- Java記憶體模型及GC演算法Java記憶體模型GC演算法
- 【三思筆記】 全面學習Oracle分割槽表及分割槽索引筆記Oracle索引
- 聊聊 記憶體模型與記憶體序記憶體模型
- 全面學習分割槽表及分割槽索引(13)--分隔表分割槽索引
- Java記憶體模型FAQ(一) 什麼是記憶體模型Java記憶體模型
- C/C++記憶體洩漏及檢測C++記憶體
- Java 記憶體模型Java記憶體模型
- Java記憶體模型Java記憶體模型
- ffmpeg記憶體模型記憶體模型
- JVM記憶體模型JVM記憶體模型
- C++ 學習筆記之 引用C++筆記
- Java多執行緒之記憶體模型Java執行緒記憶體模型