黑馬程式員匠心之作|C++教程從0到1入門編程,學習編程不再難
文章目錄
- 1 記憶體磁區模型
- 1.1 程式運行前
- 1.2 程式運行后(手動開辟記憶體:c語言malloc,c++new)
- 1.3 new運算子(在堆區開辟資料)(delete釋放記憶體)(釋放陣列delete后加[])(利用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; //10
cout << *p << endl; //10
system("pause");
return 0;
}
總結:
堆區資料由程式員管理開辟和釋放
堆區資料利用new關鍵字進行開辟記憶體
1.3 new運算子(在堆區開辟資料)(delete釋放記憶體)(釋放陣列delete后加[])(利用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; //10
cout << *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;
cout << "a = " << a << endl; //a = 10
cout << "b = " << b << endl; //a = 10
b = 100;
cout << "a = " << a << endl; //b = 100
cout << "b = " << b << endl; //b = 100
system("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; //20
cout << "b = " << b << endl; //20
cout << "c = " << c << endl; //20
system("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:20
a = 10;
b = 20;
mySwap02(&a, &b);
cout << "a:" << a << " b:" << b << endl; //a:20 b:10
a = 10;
b = 20;
mySwap03(a, b);
cout << "a:" << a << " b:" << b << endl; //a:20 b:10
system("pause");
return 0;
}
總結:通過參考引數產生的效果同按地址傳遞是一樣的,參考的語法更清楚簡單
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; //20
cout << "ref:" << ref << endl; //20
func(a);
cout << "a:" << a << endl; //100
cout << "ref:" << ref << endl; //100
return 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;
}
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; //50
cout << "ret = " << func(100) << endl; //120
cout << "ret = " << func2(100) << endl; //110
system("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 main() {
func();
func(10);
func(3.14);
func(10, 3.14);
func(3.14, 10);
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); //呼叫無const
func(10);//呼叫有const
//func2(10); //碰到默認引數產生歧義,需要避免
system("pause");
return 0;
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/300978.html
標籤:其他
上一篇:基于影像識別原理的UI自動化工具——Airtest入門
下一篇:程式員男友的一分鐘有多長?
