C++基礎精講-02

文章目錄

  • 1.C/C++申請、釋放堆空間的方式對比
    • 1.1C語言申請、釋放堆空間
    • 1.2C++申請、釋放堆空間
      • 1.2.1 new表達式申請數組空間
    • 1.3回收空間時的注意事項
    • 1.4malloc/free 和 new/delete 的區別
  • 2.引用
    • 2.1 引用的概念
    • 2.2 引用的本質
    • 2.3 引用與指針的聯系與區別
    • 2.4 引用的使用場景
      • 2.4.1 引用作為函數的參數
    • 2.5 引用作為函數的返回值
    • 2.6 總結
  • 3.強制類型轉換
    • 3.1 c語言里的強制類型轉換
    • 3.2 c++數據類型強制轉換
      • 3.2.1 static_cast(常用)
      • 3.2.3 const_cast (常不用)
      • 3.2.3 其他(后面章節中應用到在講解)


1.C/C++申請、釋放堆空間的方式對比

1.1C語言申請、釋放堆空間

關于C語言的堆內存管理內存管理不熟悉可看以下章節
C語言精講-12
c語言中申請、釋放堆空間一般用malloc和free函數

#include<stdio.h>
#include<stdlib.h>void test(void)
{//申請內存int*p=(int*) malloc(sizeof(int));if(NULL==p){printf("內存申請失敗\n");exit(0) ;}*p=10;printf("*p=%d\n",*p);//釋放內存;free(p);p=NULL;}int main(void)
{test();return 0;}

在這里插入圖片描述

1.2C++申請、釋放堆空間

c++申請、釋放堆空間一般用new/delete表達式;

#include<iostream>
using std::cout;
using std::endl;void test(void)
{//初始化為該類型的默認值int * p1 = new int();cout<<*p1<<endl;int *p2=new int(2);cout<<*p2<<endl;//釋放內存delete p1;delete p2;//將 p1 和 p2 置為 nullptr;避免野指針p1= nullptr;p2= nullptr;}int main(void)
{test();return 0;}

1.2.1 new表達式申請數組空間

1.默認初始化為0;

#include<iostream>
using std::cout;
using std::cin;
using std::endl;void test(void)
{//將動態分配的數組元素默認初始化為 0//申請10個int類型的堆空間int * p1 = new int[10]();for(int idx = 0; idx < 10; ++idx){p1[idx] = idx;}for(int idx = 0; idx < 10; ++idx){cout << p1[idx] << endl;}//釋放堆空間delete [] p1;p1=nullptr;}int main(void)
{       test();return 0;
}       
~                                       

在這里插入圖片描述
2.賦初值

#include<iostream>
using std::cout;
using std::cin;
using std::endl;void test(void)
{       //申請3個int類型的堆空間int * p1 = new int[3]{2,4,6};for(int i=0;i<3;i++){cout<<p1[i]<<endl;}//釋放堆空間delete [] p1;p1=nullptr;}int main(void)
{       test();return 0;
}       
~                           

在這里插入圖片描述

1.3回收空間時的注意事項

1.三組申請空間和回收空間的匹配組合

malloc            freenew               deletenew int[5]()      delete[]

2安全回收
delete只是回收了指針指向的空間,但這個指針變量依然還在,指向了不確定的內容(野指針),容易造成錯誤。所以需要進行安全回收,將這個指針設為空指針C++11之后使用nullptr表示空指針。

1.4malloc/free 和 new/delete 的區別

1.malloc/free 是庫函數;new/delete 是表達式,后兩者使用時不是函數的寫法;
2.new 表達式的返回值是相應類型的指針,malloc 返回值是 void*;
3.malloc 申請的空間不會進行初始化,獲取到的空間是有臟數據的,但 new 表達式申請空間時可以直接初始化;
4.malloc 的參數是字節數,new 表達式不需要傳遞字節數,會根據相應類型自動獲取空間大小。

2.引用

2.1 引用的概念

引用是c++對c的重要擴充。在c/c++中指針的作用基本都是一樣的,但是c++增加了另外一種給函數傳遞地址的途徑,這就是按引用傳遞
變量概述
1.變量名實質上是一段連續內存空間的別名,是一個標號(門牌號)
2.程序中通過變量來申請并命名內存空間
3.通過變量的名字可以使用存儲空間
c++中新增了引用的概念,引用可以作為一個已定義變量的別名。
基本語法:

Type& ref = val;
示例:
int number = 2;
int & ref = number;
#include<iostream>
using std::cout;
using std::cin;
using std::endl;int main(void)
{int sum=10;cout<<"sum="<<sum<<endl;int&s=sum;cout<<"s="<<s<<endl;s=100;cout<<"s="<<s<<endl<<"num="<<sum<<endl;return 0;
}

在這里插入圖片描述
注意事項
?&在此不是求地址運算,而是起標識作用。
?類型標識符是指目標變量的類型
?必須在聲明引用變量時進行初始化。
?引用初始化之后不能改變
?不能有NULL引用。必須確保引用是和一塊合法的存儲單元關聯。

2.2 引用的本質

引用的本質在c++內部實現是一個常指針;c++編譯器在編譯過程中使用常指針作為引用的內部實現,因此引用所占用的空間大小與指針相同,只是這個過程是編譯器內部實現,用戶不可見。

#include<iostream>
using std::cout;
using std::cin;
using std::endl;void test(void)
{int sum=10;int &s=sum;int*p=&sum;cout<<"sum的地址:"<<&sum<<endl;cout<<"s的地址:"<<&s<<endl;cout<<"p所指向的地址:"<<p<<endl;cout<<"size(p)="<<sizeof(p)<<endl;//指針p占多少字節cout<<"size(s)="<<sizeof(&s)<<endl;//引用&s占多數字節
}int main(void)
{test();return 0;
}

在這里插入圖片描述

2.3 引用與指針的聯系與區別

聯系:

  1. 引用和指針都有地址的概念,都是用來間接訪問變量;

  2. 引用的底層還是指針來完成,可以把引用視為一個常指針。

區別
4. 引用必須初始化,指針可以不初始化;
5. 引用不能修改綁定,但是指針可以修改指向;
6. 在代碼層面對引用本身取址取到的是變量本體的地址,但是對指針取址取到的是指針變量的地址

2.4 引用的使用場景

2.4.1 引用作為函數的參數

在沒有引用之前,如果我們想通過形參改變實參的值,只有使用指針才能到達目的。但使用指針的過程中,不好操作,很容易犯錯。 而引用既然可以作為其他變量的別人而存在,那在很多場合下就可以用引用代替指針,因而也具有更好的可讀性和實用性。這就是引用存在的意義。

#include<iostream>
using std::cout;
using std::cin;
using std::endl;//使用指針
void swap(int *a,int*b)
{int temp=*a;*a=*b;*b=temp;
}
//使用引用
void swap2(int&a,int&b)
{int temp=a;a=b;b=temp;
}void test1(void)
{int a=10,b=20;cout<<"交換前:a="<<a<<",b="<<b<<endl;swap(&a,&b);cout<<"交換后:a="<<a<<",b="<<b<<endl;swap2(a,b);cout<<"再次交換后:a="<<a<<"b="<<b<<endl;
}
int main(void)
{test1();return 0;
}

在這里插入圖片描述

2.5 引用作為函數的返回值

當以引用作為函數的返回值時,返回的變量其生命周期一定是要大于函數的生命周期的,即當函數執行完畢時,返回的變量還存在。
目的: 避免復制,節省開銷

#include<iostream>
using std::cout;
using std::cin;
using std::endl;int fun1(void)
{int a=10;//返回的是a的副本,變量a是局部變量。在fun1函數結束時a的空間就被回收cout<<"fun a的地址:"<<&a<<endl;return a;
}int& fun2(void)
{///使用指針/引用作為返回值時候,不可返回一個局部的變量;可加static修飾static int  b=100;//返回的是一個綁定b的的引用;cout<<"fun2 b的地址:"<<&b<<endl;return b;
}int main(void)
{//把fun1中a的值復制給main函數中的變量a;int a=fun1();cout<<"main中a的地址:"<<&a<<endl;int &b=fun2();cout<<"main 中引用b的地址:"<<&b<<endl;return 0;
}

在這里插入圖片描述
注意事項
1.不要返回局部變量的引用。因為局部變量會在函數返回后被銷毀,被返回的引用就成為了"無所指"的引用,程序會進入未知狀態。
2.不要輕易返回一個堆空間變量的引用,非常容易造成內存泄漏。

int & func()
{int * pint = new int(1);return *pint;
}void test()
{int a = 2, b = 4;int c = a + func() + b;//內存泄漏
}

2.6 總結

  1. 在引用的使用中,單純給某個變量取個別名沒有什么意義,引用的目的主要用于在函數參數傳遞中,解決大塊數據或對象的傳遞效率和空間不理想的問題。
  2. 用引用傳遞函數的參數,能保證參數傳遞中不產生副本,提高傳遞的效率,還可以通過const的使用,保證了引用傳遞的安全性。
  3. 引用與指針的區別是,指針通過某個指針變量指向一個變量后,對它所指向的變量間接操作。程序中使用指針,程序的可讀性差;引用底層仍然是指針,但是編譯器不允許訪問到這個底層的指針,邏輯上簡單理解為——對引用的操作就是對目標變量的操作。可以用指針或引用解決的問題,更推薦使用引用

3.強制類型轉換

3.1 c語言里的強制類型轉換

格式:數據類型 變量1 = (數據類型)變量2;

#include<stdio.h>int main(void)
{       float a=3.14f;printf("a=%f\n",a);int b=(int)a;printf("b=%d\n",b);return 0;
}       

缺點:

  1. 數據丟失風險高
    C 語言的強制類型轉換語法簡單,不過在將大類型轉換為小類型時,容易發生數據丟失。比如把long類型轉換為int類型,若long類型的值超出int類型的范圍,就會出現數據截斷。
  2. 破壞類型系統且缺乏安全性檢查
    C 語言允許進行各種類型的強制轉換,像指針類型的轉換,這可能會破壞類型系統的安全性,編譯器也不會做嚴格的類型檢查。例如將void*指針轉換為其他類型的指針,若使用不當,就會引發未定義行為。
  3. 掩蓋潛在錯誤
    C 語言的強制類型轉換可能會掩蓋代碼中的潛在錯誤,使代碼能通過編譯,但實際上邏輯可能存在問題。
  4. 可移植性差
    不同平臺上數據類型的大小和表示方式可能不同,C 語言的強制類型轉換可能會導致在不同平臺上產生不同的結果,影響代碼的可移植性。

3.2 c++數據類型強制轉換

3.2.1 static_cast(常用)

最常用的類型轉換符,在正常狀況下的類型轉換, 用于將一種數據類型轉換成另一種數據類型,如把int轉換為float

目標類型 轉換后的變量 = static_cast<目標類型>(要轉換的變量)

好處:不允許非法的轉換發生;方便查找

int a = 100float f = 0;
f = (float) a;//C風格
f = static_cast<float>(a);
void * p1 = malloc(sizeof(int));
int * p2 = static_cast<int*>(p1);
*p2 = 1;

不能完成任意兩個指針類型間的轉換(限制一些非法轉換)

int a = 1;
int * p1 = &a;
float * p2 = static_cast<float *>(p1);//錯誤

總結,static_cast的用法主要有以下幾種:

1)用于基本數據類型之間的轉換,如把int轉換成char,把int轉換成enum。這種轉換的安全性需要開發人員來保證;
2)把void指針轉換成目標類型的指針,但不安全;
3)把任何類型的表達式轉換成void類型;
4)用于類層次結構中基類和子類之間指針或引用的轉換

3.2.3 const_cast (常不用)

該運算符用來修改類型的const屬性。
指向常量的指針被轉化成普通指針,并且仍然指向原來的對象;
常量引用被轉換成非常量引用,并且仍然指向原來的對象;

const int number = 100;
int * pInt = &number;//error
int * pInt2 = const_cast<int *>(&number);

3.2.3 其他(后面章節中應用到在講解)

dynamic_cast:該運算符主要用于基類和派生類間的轉換;
reinterpret_cast:功能強大,慎用(也稱為萬能轉換);

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/bicheng/76419.shtml
繁體地址,請注明出處:http://hk.pswp.cn/bicheng/76419.shtml
英文地址,請注明出處:http://en.pswp.cn/bicheng/76419.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Spring Boot MongoDB 分頁工具類封裝 (新手指南)

Spring Boot MongoDB 分頁工具類封裝 (新手指南) 目錄 引言&#xff1a;為何需要分頁工具類&#xff1f;工具類一&#xff1a;PaginationUtils - 簡化 Pageable 創建 設計目標代碼實現 (PaginationUtils.java)如何使用 PaginationUtils 工具類二&#xff1a;PageResponse<…

MyBatis的緩存、逆向工程、使用PageHelper、使用PageHelper

一、MyBatis的緩存 緩存&#xff1a;cache 緩存的作用&#xff1a;通過減少IO的方式&#xff0c;來提高程序的執行效率。 mybatis的緩存&#xff1a;將select語句的查詢結果放到緩存&#xff08;內存&#xff09;當中&#xff0c;下一次還是這條select語句的話&#xff0c;直…

java中的JNI調用c庫

1. 簡單demo 如果是在某個項目中有包名就需要自己找ai問問去改寫下cmd命令去編譯執行等 java文件&#xff08;HelloJNI.java&#xff09; public class HelloJNI {// 聲明 native 方法public native void sayHello();// 加載本地庫static {System.loadLibrary("hello&quo…

人工智能:GPT技術應用與未來展望

GPT(Generative Pre-trained Transformer)作為自然語言處理領域的代表性技術,近年來在各行業的實際應用中展現出廣泛潛力。結合其技術特性與行業需求,以下是GPT的主要應用場景、案例分析及未來挑戰的總結: 一、核心應用領域與案例 文本生成與內容創作 自動化內容生產:GPT…

前端筆記-ECMAScript語法概覽

更多詳細可以查看1.1 ES6 教程 | 菜鳥教程 這里我將大概記錄ES與JS大概不一樣的部分&#xff0c;方便聯合記憶。 歷史與關系 ECMAScript&#xff1a;是一種由 Ecma 國際組織制定的腳本語言規范&#xff0c;它是 JavaScript 的標準化版本。ECMAScript 為 JavaScript 提供了語…

操作主機的管理

1.在AD林范圍內&#xff0c;有哪幾個操作主機角色 架構主機&#xff08;Schema Master&#xff09; 功能&#xff1a;負責整個AD林中所有對象和屬性的定義&#xff0c;是唯一可以更新目錄架構的DC。架構更新會從架構主機復制到目錄林中的所有其他域控制器。 作用范圍&#xf…

【Linux】網絡編程

目錄 端口號 網絡字節序 socket編程 接口 sockaddr結構 udp網絡程序 創建套接字 綁定 接收 發送 客戶端需要綁定嗎&#xff1f; 客戶端執行方法 本地環回地址 終端文件 代碼 tcp網絡程序 SOCK_STREAM 監聽 查詢網絡信息 獲取新連接 地址轉換函數 客戶端綁…

Go 語言中的select是做什么的

Go 語言中的 select 是做什么的 在 Go 語言中&#xff0c;select 語句是用于處理多個通道&#xff08;channel&#xff09;操作的一種控制結構。它類似于 switch 語句&#xff0c;但專門用于并發編程&#xff0c;允許 Goroutine 在多個通道上等待操作&#xff08;發送或接收&a…

智慧班牌系統解決方案,SaaS智慧電子班牌云平臺

智慧班牌系統解決方案 系統概述 智慧班牌是智慧校園建設不斷發展的產物&#xff0c;是教育信息化改革的載體。通過智慧班牌可以高效便捷傳遞各種知識信息和通知信息、及時反饋課堂信息、實現班級的透明化管理。智慧班牌將學生平安考勤、異常出勤情況及時反饋至家長、老師&…

利用大模型和聚類算法找出 Excel 文件中重復或相似度高的數據,并使用 FastAPI 進行封裝的詳細方案

以下是一個利用大模型和聚類算法找出 Excel 文件中重復或相似度高的數據,并使用 FastAPI 進行封裝的詳細方案: 方案流程 數據讀取:從 Excel 文件中讀取數據。文本向量化:使用大模型將文本數據轉換為向量表示。聚類分析:運用聚類算法對向量進行分組,將相似度高的數據歸為…

【Docker基礎】容器技術詳解:生命周期、命令與實戰案例

文章目錄 一、什么是容器&#xff1f;二、為什么需要容器三、容器的生命周期容器狀態容器OOM容器異常退出容器異常退出容器暫停 四、容器命令命令清單詳細介紹 五、容器操作案例容器的狀態遷移容器批量操作容器交互模式attached 模式detached 模式interactive 模式 容器 與 宿主…

Laravel 實現 隊列 發送郵件功能

一. 什么是隊列 在構建 Web 應用程序時&#xff0c;你可能需要執行一些任務&#xff0c;例如解析文件&#xff0c;發送郵件&#xff0c;大量的數據計算等等&#xff0c;這些任務在典型的 Web 請求期間需要很長時間才能執行。 慶幸的是&#xff0c;Laravel 可以創建在后臺運行…

flink Shuffle的總結

關于 ** ?5 種 Shuffle 類型** 的區別、使用場景及 Flink 版本支持的總結&#xff1a; * 注意:下面是問AI具體細節與整理學習 1. 核心區別 Shuffle 類型核心特點使用場景Flink 版本支持Pipelined Shuffle流式調度&#xff0c;純內存交換&#xff0c;低延遲&#xff08;毫秒級…

Git使用與管理

一.基本操作 1.創建本地倉庫 在對應文件目錄下進行&#xff1a; git init 輸入完上面的代碼&#xff0c;所在文件目錄下就會多一個名為 .git 的隱藏文件&#xff0c;該文件是Git用來跟蹤和管理倉庫的。 我們可以使用 tree 命令&#xff08;注意要先下載tree插件&#xff09…

計算機視覺——深度學習圖像處理中目標檢測平均精度均值(mAP)與其他常用評估指標

概述 平均精度均值&#xff08;mAP&#xff09;是目標檢測領域中最為流行且復雜的重要評估指標之一。它廣泛用于綜合總結目標檢測器的性能。許多目標檢測模型會輸出類似以下的參數結果&#xff1a; Average Precision (AP) [ IoU0.50:0.95 | area all | maxDets100 ] 0.3…

C語言中單鏈表操作:查找節點與刪除節點

一. 簡介 前面學習了C語言中創建鏈表節點&#xff0c;向鏈表中插入節點等操作&#xff0c;文章如下&#xff1a; C語言中單向鏈表&#xff1a;創建節點與插入新節點-CSDN博客 本文繼續學習c語言中對鏈表的其他操作&#xff0c;例如在鏈表中查找某個節點&#xff0c;刪除鏈表…

WePY 框架:小程序開發的“Vue式”利器!!!

WePY 框架&#xff1a;小程序開發的“Vue式”利器 &#x1f680; 哈嘍&#xff0c;大家好&#xff01;&#x1f44b; 今天我們要聊聊一個在微信小程序開發中大放異彩的框架——WePY&#xff01;它是什么&#xff1f;有什么特點&#xff1f;為啥值得一試&#xff1f;別急&#…

什么是微前端?有什么好處?有哪一些方案?

微前端&#xff08;Micro Frontends&#xff09; 微前端是一種架構理念&#xff0c;借鑒了微服務的思想&#xff0c;將一個大型的前端應用拆分為多個獨立、自治的子應用&#xff0c;每個子應用可以由不同團隊、使用不同技術棧獨立開發和部署&#xff0c;最終聚合為一個整體產品…

【家政平臺開發(33)】庫存管理模塊開發實戰:從基礎搭建到智能管控

本【家政平臺開發】專欄聚焦家政平臺從 0 到 1 的全流程打造。從前期需求分析,剖析家政行業現狀、挖掘用戶需求與梳理功能要點,到系統設計階段的架構選型、數據庫構建,再到開發階段各模塊逐一實現。涵蓋移動與 PC 端設計、接口開發及性能優化,測試階段多維度保障平臺質量,…

Mysql個人筆記

Mysql個人筆記 sql基礎書寫規則和種類種類書寫規則注釋規則啟動 DDL數據類型數據庫的操作useshowcreatedrop 表的操作useshowcreate創建表復制表 dropalter Mysql的存儲引擎 DMLselectselect語句like&#xff08;謂詞&#xff09;where聚合函數&#xff1a;關于nullgroup byexi…