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

歡迎訪問 生活随笔!

生活随笔

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

c/c++

【黑马程序员 C++教程从0到1入门编程】【笔记3】C++核心编程(内存分区模型、引用、函数提高)

發布時間:2025/3/20 c/c++ 15 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【黑马程序员 C++教程从0到1入门编程】【笔记3】C++核心编程(内存分区模型、引用、函数提高) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

黑馬程序員匠心之作|C++教程從0到1入門編程,學習編程不再難

文章目錄

    • 1 內存分區模型
      • 1.1 程序運行前
      • 1.2 程序運行后(手動開辟內存:c語言malloc,c++new)
      • 1.3 new操作符(在堆區開辟數據)(delete釋放內存)(釋放數組delete后加[]:寫成`delete[] arr`)(利用new創建的數據,會返回該數據對應的類型的指針)
    • 2 引用
      • 2.1 引用的基本使用(給變量起別名)(語法:int& b = a;)(對引用的操作相當于對被引用變量的操作)
      • 2.2 引用注意事項
      • 2.3 引用做函數參數
      • 2.4 引用做函數返回值(簡單解釋了引用的原理)(本質是指針常量)
      • 2.6 常量引用(在函數形參列表中,可以加==const修飾形參==,防止形參改變實參)
        • 傳常量引用,既有能獲取其被引變量地址的功能,又有防止誤修改的功能
    • 3 函數提高
      • 3.1 函數默認參數(只能見招拆招了,但是又怕那種報錯信息不全的,,。。)
      • 3.2 函數占位參數(暫時不知道有什么用?)
      • 3.3 函數重載
        • 3.3.1 函數重載概述(條件:同一個作用域下、函數名稱相同、函數參數**類型不同** 或者 **個數不同** 或者 **順序不同**)
        • 3.3.2 函數重載注意事項(引用作為重載條件【有的有優先級】、函數重載碰到函數默認參數【需要避免歧義】)

本階段主要針對C++ 面向對象編程技術做詳細講解,探討C++中的核心和精髓。

1 內存分區模型

C++程序在執行時,將內存大方向劃分為4個區域

  • 代碼區:存放函數體的二進制代碼,由操作系統進行管理的
  • 全局區:存放全局變量和靜態變量以及常量
  • 棧區:由編譯器自動分配釋放, 存放函數的參數值,局部變量等
  • 堆區:由程序員分配和釋放,若程序員不釋放,程序結束時由操作系統回收

內存四區意義:

不同區域存放的數據,賦予不同的生命周期, 給我們更大的靈活編程

1.1 程序運行前

? 在程序編譯后,生成了exe可執行程序,未執行該程序前分為兩個區域

? 代碼區:

? 存放 CPU 執行的機器指令

? 代碼區是共享的,共享的目的是對于頻繁被執行的程序,只需要在內存中有一份代碼即可

? 代碼區是只讀的,使其只讀的原因是防止程序意外地修改了它的指令

? 全局區:

? 全局變量和靜態變量存放在此.

? 全局區還包含了常量區, 字符串常量和其他常量也存放在此.

? 該區域的數據在程序結束后由操作系統釋放.

示例:

#include<iostream> #include<string> using namespace std;//全局變量 int g_a = 10; int g_b = 10;//全局常量 const int c_g_a = 10; const int c_g_b = 10;int main() {//局部變量int a = 10;int b = 10;//打印地址cout << "局部變量a地址為: " << (int)&a << endl;cout << "局部變量b地址為: " << (int)&b << endl;cout << "全局變量g_a地址為: " << (int)&g_a << endl;cout << "全局變量g_b地址為: " << (int)&g_b << endl;//靜態變量static int s_a = 10;static int s_b = 10;cout << "靜態變量s_a地址為: " << (int)&s_a << endl;cout << "靜態變量s_b地址為: " << (int)&s_b << endl;cout << "字符串常量地址為: " << (int)&"hello world" << endl;cout << "字符串常量地址為: " << (int)&"hello world1" << endl;cout << "全局常量c_g_a地址為: " << (int)&c_g_a << endl;cout << "全局常量c_g_b地址為: " << (int)&c_g_b << endl;const int c_l_a = 10;const int c_l_b = 10;cout << "局部常量c_l_a地址為: " << (int)&c_l_a << endl;cout << "局部常量c_l_b地址為: " << (int)&c_l_b << endl;system("pause");return 0; }

運行結果:

局部變量a地址為: 9435484 局部變量b地址為: 9435472 全局變量g_a地址為: 10731520 全局變量g_b地址為: 10731524 靜態變量s_a地址為: 10731528 靜態變量s_b地址為: 10731532 字符串常量地址為: 10722292 字符串常量地址為: 10722308 全局常量c_g_a地址為: 10722096 全局常量c_g_b地址為: 10722100 局部常量c_l_a地址為: 9435460 局部常量c_l_b地址為: 9435448


總結:

  • C++中在程序運行前分為全局區和代碼區
  • 代碼區特點是共享和只讀
  • 全局區中存放全局變量、靜態變量、常量
  • 常量區中存放 const修飾的全局常量 和 字符串常量

1.2 程序運行后(手動開辟內存:c語言malloc,c++new)

? 棧區:

? 由編譯器自動分配釋放, 存放函數的參數值,局部變量等

? 注意事項:不要返回局部變量的地址,棧區開辟的數據由編譯器自動釋放

示例:

#include<iostream> #include<string> using namespace std;int* func() {int a = 10;return &a; }int main() {int* p = func();cout << *p << endl; //10 cout << *p << endl; //2057673096 //地址被自動釋放了system("pause");return 0; }

? 堆區:

? 由程序員分配釋放,若程序員不釋放,程序結束時由操作系統回收

? 在C++中主要利用new在堆區開辟內存

示例:

#include<iostream> #include<string> using namespace std;int* func() {int* a = new int(10);return a; }int main() {int* p = func();cout << *p << endl; //10cout << *p << endl; //10system("pause");return 0; }

總結:

堆區數據由程序員管理開辟和釋放

堆區數據利用new關鍵字進行開辟內存

1.3 new操作符(在堆區開辟數據)(delete釋放內存)(釋放數組delete后加[]:寫成delete[] arr)(利用new創建的數據,會返回該數據對應的類型的指針)

? C++中利用new操作符在堆區開辟數據

? 堆區開辟的數據,由程序員手動開辟,手動釋放,釋放利用操作符 delete

? 語法:new 數據類型

? 利用new創建的數據,會返回該數據對應的類型的指針

示例1: 基本語法

#include<iostream> #include<string> using namespace std;int* func() {int* a = new int(10);return a; }int main() {int* p = func();cout << *p << endl; //10cout << *p << endl; //10//利用delete釋放堆區數據delete p;//cout << *p << endl; //報錯,釋放的空間不可訪問system("pause");return 0; }

示例2:開辟數組

#include<iostream> #include<string> using namespace std;//堆區開辟數組 int main() {int* arr = new int[10];for (int i = 0; i < 10; i++){arr[i] = i + 100;}for (int i = 0; i < 10; i++){cout << arr[i] << endl;}//釋放數組 delete 后加 []delete[] arr;system("pause");return 0; }

運行結果:

100 101 102 103 104 105 106 107 108 109

2 引用

2.1 引用的基本使用(給變量起別名)(語法:int& b = a;)(對引用的操作相當于對被引用變量的操作)

作用: 給變量起別名

語法: 數據類型 &別名 = 原名

示例:

#include<iostream> #include<string> using namespace std;int main() {int a = 10;int& b = a; //b的內存地址跟a的內存地址相同cout << "a = " << a << endl; //a = 10cout << "b = " << b << endl; //a = 10b = 100;cout << "a = " << a << endl; //b = 100cout << "b = " << b << endl; //b = 100system("pause");return 0; }

2.2 引用注意事項

  • 引用必須初始化
  • 引用在初始化后,不可以改變

示例:
(更改引用的值,被引用的變量的值也會跟著改變,因為它們是同一個內存地址)

#include<iostream> #include<string> using namespace std;int main() {int a = 10;int b = 20;//int &c; //錯誤,引用必須初始化int& c = a; //一旦初始化后,就不可以更改c = b; //這是賦值操作,不是更改引用cout << "a = " << a << endl; //20cout << "b = " << b << endl; //20cout << "c = " << c << endl; //20system("pause");return 0; }

2.3 引用做函數參數

作用:函數傳參時,可以利用引用的技術讓形參修飾實參

優點:可以簡化指針修改實參

示例:

#include<iostream> #include<string> using namespace std;//1. 值傳遞 void mySwap01(int a, int b) {int temp = a;a = b;b = temp; }//2. 地址傳遞 void mySwap02(int* a, int* b) {int temp = *a;*a = *b;*b = temp; }//3. 引用傳遞 void mySwap03(int& a, int& b) {int temp = a;a = b;b = temp; }int main() {int a = 10;int b = 20;mySwap01(a, b);cout << "a:" << a << " b:" << b << endl; //a:10 b:20a = 10;b = 20;mySwap02(&a, &b);cout << "a:" << a << " b:" << b << endl; //a:20 b:10a = 10;b = 20;mySwap03(a, b); cout << "a:" << a << " b:" << b << endl; //a:20 b:10system("pause");return 0; }

總結:通過引用參數產生的效果同按地址傳遞是一樣的。引用的語法更清楚簡單
(Dontla:我沒覺得簡單!!!!還引用了新的語法。。。。)

2.4 引用做函數返回值(簡單解釋了引用的原理)(本質是指針常量)

作用:引用是可以作為函數的返回值存在的

注意:不要返回局部變量引用

用法:函數調用作為左值

示例:

#include<iostream> #include<string> using namespace std;//發現是引用,轉換為 int* const ref = &a; void func(int& ref) {ref = 100; // ref是引用,轉換為*ref = 100 } int main() {int a = 10;//自動轉換為 int* const ref = &a; 指針常量是指針指向不可改,也說明為什么引用不可更改int& ref = a;ref = 20; //內部發現ref是引用,自動幫我們轉換為: *ref = 20;cout << "a:" << a << endl; //20cout << "ref:" << ref << endl; //20func(a);cout << "a:" << a << endl; //100cout << "ref:" << ref << endl; //100return 0; }

結論:C++推薦用引用技術,因為語法方便,引用本質是指針常量,但是所有的指針操作編譯器都幫我們做了

2.6 常量引用(在函數形參列表中,可以加const修飾形參,防止形參改變實參)

作用:常量引用主要用來修飾形參,防止誤操作

在函數形參列表中,可以加const修飾形參,防止形參改變實參

示例:

#include<iostream> #include<string> using namespace std;//引用使用的場景,通常用來修飾形參 void showValue(const int& v) {//v += 10;cout << v << endl; //10 }int main() {//int& ref = 10; 引用本身需要一個合法的內存空間,因此這行錯誤//加入const就可以了,編譯器優化代碼,int temp = 10; const int& ref = temp;const int& ref = 10;//ref = 100; //加入const后不可以修改變量cout << ref << endl; //10//函數中利用常量引用防止誤操作修改實參int a = 10;showValue(a);system("pause");return 0; }

傳常量引用,既有能獲取其被引變量地址的功能,又有防止誤修改的功能

如果要修改,可采用這個辦法

#include<iostream> #include<string> using namespace std;int main() {int b = 10;const int& ref = b;//ref++; //不允許操作*((int*)(&ref)) = 0;printf("b = %d, ref = %d\n", b, ref); //b = 0, ref = 0system("pause");return 0; }

3 函數提高

3.1 函數默認參數(只能見招拆招了,但是又怕那種報錯信息不全的,,。。)

在C++中,函數的形參列表中的形參是可以有默認值的。

語法:返回值類型 函數名 (參數= 默認值){}

示例:

#include<iostream> #include<string> using namespace std;int func(int a, int b = 10, int c = 10) {return a + b + c; }//1. 如果某個位置參數有默認值,那么從這個位置往后,從左向右,必須都要有默認值 //2. 如果函數聲明有默認值,函數實現的時候就不能有默認參數(否則會報錯:重定義默認參數) int func2(int a = 10, int b = 10); int func2(int a, int b) {return a + b; }int main() {cout << "ret = " << func(20, 20) << endl; //50cout << "ret = " << func(100) << endl; //120cout << "ret = " << func2(100) << endl; //110system("pause");return 0; }

3.2 函數占位參數(暫時不知道有什么用?)

C++中函數的形參列表里可以有占位參數,用來做占位,調用函數時必須填補該位置

語法: 返回值類型 函數名 (數據類型){}

在現階段函數的占位參數存在意義不大,但是后面的課程中會用到該技術

示例:

#include<iostream> #include<string> using namespace std;//函數占位參數 ,占位參數也可以有默認參數 void func(int a, int) {cout << "this is func" << endl; //this is func }int main() {func(10, 10); //占位參數必須填補system("pause");return 0; }

3.3 函數重載

3.3.1 函數重載概述(條件:同一個作用域下、函數名稱相同、函數參數類型不同 或者 個數不同 或者 順序不同

作用:函數名可以相同,提高復用性

函數重載滿足條件:

  • 同一個作用域下
  • 函數名稱相同
  • 函數參數類型不同 或者 個數不同 或者 順序不同

注意: 函數的返回值不可以作為函數重載的條件(但是注意,如果參數的重載條件滿足,則返回值可以更改!!)

示例:

#include<iostream> #include<string> using namespace std;//函數重載需要函數都在同一個作用域下 void func() {cout << "func 的調用!" << endl; } void func(int a) {cout << "func (int a) 的調用!" << endl; } void func(double a) {cout << "func (double a)的調用!" << endl; } void func(int a, double b) {cout << "func (int a ,double b) 的調用!" << endl; } void func(double a, int b) {cout << "func (double a ,int b)的調用!" << endl; }//函數返回值不可以作為函數重載條件 //int func(double a, int b) //{ // cout << "func (double a ,int b)的調用!" << endl; //}//參數的重載條件滿足,則返回值可以更改!! int func(double a, int b, int c) {cout << "func (double a ,int b)的調用!" << endl;return 0; }int main() {func();func(10);func(3.14);func(10, 3.14);func(3.14, 10);func(3.14, 10,20);system("pause");return 0; }

3.3.2 函數重載注意事項(引用作為重載條件【有的有優先級】、函數重載碰到函數默認參數【需要避免歧義】)

  • 引用作為重載條件
  • 函數重載碰到函數默認參數

示例:

#include<iostream> #include<string> using namespace std;//函數重載注意事項 //1、引用作為重載條件void func(int& a) {cout << "func (int &a) 調用 " << endl; }void func(const int& a) {cout << "func (const int &a) 調用 " << endl; }//2、函數重載碰到函數默認參數void func2(int a, int b = 10) {cout << "func2(int a, int b = 10) 調用" << endl; }void func2(int a) {cout << "func2(int a) 調用" << endl; }int main() {int a = 10;func(a); //調用無constfunc(10);//調用有const//func2(10); //碰到默認參數產生歧義,需要避免system("pause");return 0; }

注意:調用func(a)時,func(int& a);和func(const int& a);都能被調用到,優先調用func(int& a);

總結

以上是生活随笔為你收集整理的【黑马程序员 C++教程从0到1入门编程】【笔记3】C++核心编程(内存分区模型、引用、函数提高)的全部內容,希望文章能夠幫你解決所遇到的問題。

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