C++基礎問題

C++基礎問題

掌握形參默認帶缺省值的函數

函數調用時

#include <iostream>int sum(int a, int b = 20) {return a + b;
}int main() {int a = 10, b = 20;int ret = sum(a, b);cout << "ret: " << ret << endl;ret = sum(a);/*a 使用默認值壓棧: 時壓入 a 的值和 20.push 14Hmov ecx, dowrd ptr[ebp - 4]push ecxcall sum*/ret = sum();// 壓入 10 和 20.
}

總的來說,函數效率有所增長:減少一次 push 指令。

帶有缺省的函數的聲明

// 一個缺省只能被聲明一次,并且只能被從右向左聲明
#if 1    // 編譯通過
int sum(int a = 10, int b = 20);
#elif    // 報錯: 默認值只能給一次
int sum(int a = 10, int b = 20);
int sum(int a, int b = 20);
#elif    // 編譯通過
int sum(int a, int b = 20);
int sum(int a = 10, int b);
#endifint main() {int a = 10, b = 20;int ret = sum(a, b);cout << "ret: " << ret << endl;ret = sum(a);/*a 使用默認值壓棧: 時壓入 a 的值和 20.push 14Hmov ecx, dowrd ptr[ebp - 4]push ecxcall sum*/ret = sum();// 壓入 10 和 20.
}int sum(int a, int b) {return a + b;
}

掌握內聯函數

內聯函數和普通函數的區別?

  • 內聯函數:在編譯過程中沒有函數調用的開銷,因為在函數的調用點函數被直接展開處理。
  • 內聯函數將不再產生相應的函數符號。
  • 函數定義時加上inline并不一定會讓函數變成內聯函數,僅僅是對編譯器的一種建議。如遞歸很可能不會被處理為內聯函數。
#include <iostream>using namespace std;#define IS_INLINE   1#if IS_INLINE
inline 
#endifint sum(int a, int b = 20) {return a + b;
}int main() {int a = 10, b = 20;int ret = sum(a, b);// 此處有標準的函數調用過程// 當函數調用的開銷的占比過高,建議使用內聯函數cout << "ret: " << ret << endl;}

注意:inline 在 debug 版本上是不起作用的。

驗證:inline 在 release 版能出現

chipen@ubuntu:~/code/inlineTest$ cat main.cpp
#include <iostream>using namespace std;int sum(int a, int b) {return a + b;}int main() {int a = 10, b = 20;int ret = sum(a, b);return 0;}
chipen@ubuntu:~/code/inlineTest$ g++ -c main.cpp -O2
chipen@ubuntu:~/code/inlineTest$ objdump -t main.omain.o:     file format elf64-x86-64SYMBOL TABLE:
0000000000000000 l    df *ABS*    0000000000000000 main.cpp
0000000000000000 l    d  .text    0000000000000000 .text
0000000000000000 l    d  .text.startup    0000000000000000 .text.startup
0000000000000000         *UND*    0000000000000000 _ZSt21ios_base_library_initv
0000000000000000 g     F .text    0000000000000008 _Z3sumii    # sum 函數的符號
0000000000000000 g     F .text.startup    0000000000000007 mainchipen@ubuntu:~/code/inlineTest$ vim main.cpp    # 給 sum 函數加上 inline
chipen@ubuntu:~/code/inlineTest$ g++ -c main.cpp -O2
chipen@ubuntu:~/code/inlineTest$ objdump -t main.omain.o:     file format elf64-x86-64SYMBOL TABLE:
0000000000000000 l    df *ABS*    0000000000000000 main.cpp
0000000000000000 l    d  .text.startup    0000000000000000 .text.startup
0000000000000000         *UND*    0000000000000000 _ZSt21ios_base_library_initv
0000000000000000 g     F .text.startup    0000000000000007 main
# 可見,添加內聯以后,sum 函數不再有對應的符號,而是被直接替換
chipen@ubuntu:~/code/inlineTest$ g++ -c main.cpp -O0
chipen@ubuntu:~/code/inlineTest$ objdump -t main.omain.o:     file format elf64-x86-64SYMBOL TABLE:
0000000000000000 l    df *ABS*    0000000000000000 main.cpp
0000000000000000 l    d  .text    0000000000000000 .text
0000000000000000 l    d  .text._Z3sumii    0000000000000000 .text._Z3sumii
0000000000000000 l     O .rodata    0000000000000001 _ZNSt8__detail30__integer_to_chars_is_unsignedIjEE
0000000000000001 l     O .rodata    0000000000000001 _ZNSt8__detail30__integer_to_chars_is_unsignedImEE
0000000000000002 l     O .rodata    0000000000000001 _ZNSt8__detail30__integer_to_chars_is_unsignedIyEE
0000000000000000         *UND*    0000000000000000 _ZSt21ios_base_library_initv
0000000000000000  w    F .text._Z3sumii    0000000000000018 _Z3sumii
0000000000000000 g     F .text    0000000000000033 main
# 在只用 -O0 的低優化等級時,inline 需求依然被忽略,可見 inline 只是一種建議行為

函數重載

chipen@ubuntu:~/code/inlineTest$ cat test01.cpp 
#include <iostream>
#include <cstring>using namespace std;bool compare(int a, int b) {cout << "int, int" << endl;return a > b;
}bool compare(double a, double b) {cout << "double, double" << endl;return a > b;
}bool compare(const char *a, const char *b) {cout << "const char*, const char*" << endl;return strcmp(a, b) > 0;
} int main() {compare(10, 20);compare(10.0, 20.0);compare("hello", "world");return 0;
}
chipen@ubuntu:~/code/inlineTest$ ./test01 
int, int
double, double
const char*, const char*

注意1: 一組重載函數指的是: 在同一作用域下的, 函數名相同作用域不同的函數

如當嘗試在 main 函數中添加如下聲明

chipen@ubuntu:~/code/inlineTest$ cat test01.cpp 
#include <iostream>
#include <cstring>using namespace std;bool compare(int a, int b) {cout << "int, int" << endl;return a > b;
}bool compare(double a, double b) {cout << "double, double" << endl;return a > b;
}bool compare(const char *a, const char *b) {cout << "const char*, const char*" << endl;return strcmp(a, b) > 0;
} int main() {bool compare(int a, int b);compare(10, 20);compare(10.0, 20.0);compare("hello", "world");return 0;
}
chipen@ubuntu:~/code/inlineTest$ g++ test01.cpp -o test01
test01.cpp: In function ‘int main()’:
test01.cpp:26:17: error: invalid conversion from ‘const char*’ to ‘int’ [-fpermissive]26 |         compare("hello", "world");|                 ^~~~~~~|                 ||                 const char*
test01.cpp:23:26: note:   initializing argument 1 of ‘bool compare(int, int)23 |         bool compare(int a, int b);|                      ~~~~^
test01.cpp:26:26: error: invalid conversion from ‘const char*’ to ‘int’ [-fpermissive]26 |         compare("hello", "world");|                          ^~~~~~~|                          ||                          const char*
test01.cpp:23:33: note:   initializing argument 2 of ‘bool compare(int, int)23 |         bool compare(int a, int b);|                             ~~~~^

注意2:同一類型,加不加const在編譯器眼中沒有區別。

void func(int a) {}
void func(const int a) {}
// 報錯void func(int *a) {}
void func(const int *a) {}
// 編譯通過void func(int *a) {}
void func(int const *a) {}
// 報錯

為什么 C++ 支持函數重載,C 語言不支持函數重載?

在對符號表中函數命名時,C++采取了更能準確描述一個函數的命名方式,而 C 語言直接用函數名字作為符號名。

因此,C 和 C++ 中的函數由于函數名不同,不能直接調用,會在鏈接時發生無法解析的外部符號的錯誤,因為在符號表中找不到對應的函數符號名。

要實現 C 和 C++ 之間都可以調用的函數,應該這樣定義

#ifdef __cplusplus
extern "C" {
#endif
int sum(int a, int b) {return a + b;
}
#ifdef __cplusplus
}
#endif

掌握const的用法

基本理解:const 修飾的常變量不能作為左值使用。
常變量 != 常量,例如:

chipen@ubuntu:~/code/inlineTest$ cat test02.cpp 
#include <cstdio>int main() {const int a = 20;int *p = (int *)&a;*p = 30;printf("%d %d %d\n", a, *p, *(&a));return 0;        
}
chipen@ubuntu:~/code/inlineTest$ ./test02
20 30 30

這是個不可思議的現象。原因是:在編譯器的前端階段,a 被認為是不可能被修改的,故在后文中被做了直接替換,但是 *p, *(&a) 要求必須訪問內存,故得到了 20 30 30。

證明這是一種優化行為:

chipen@ubuntu:~/code/inlineTest$ cat test02.cpp 
#include <cstdio>int main() {volatile const int a = 20;    # 不讓編譯器優化 aint *p = (int *)&a;*p = 30;printf("%d %d %d\n", a, *p, *(&a));return 0;        
}
chipen@ubuntu:~/code/inlineTest$ ./test02
30 30 30    # 符合預期

const修飾的量常出現的錯誤是:

  • 常量不能再作為左值 <= 直接修改常量的值
  • 不能把常量的地址泄露給一個普通的指針或者普通的引用變量 <= 可能間接修改常量的值

const和一級指針的結合:(const修飾的是離它最近的類型)

  • const int * p -> 指針指向的變量不能修改
  • int const * p -> 同上
  • int *const p -> 指針本身不能修改
  • const int *const p -> 指針本身和指針所指的變量都不能修改
int a = 10;            
int *p1 = &a;            // 通過, 無類型轉換
const int *p2 = &a;        // 隱式類型轉換
int *const p3 = &a;        // 隱式類型轉換
const int b = 10;
int *p4 = &b;            // 不通過, (const int *) -> (int *)
const int *p5 = &b;        // 通過
int *const p6 = &b;        // 不通過, (const int *) -> (int *const)// 總結: 權限只能縮小不能擴大

const和二級/多級指針的結合

int a = 20;
int *p = &a;
const int **p1 = &p;
// 典型錯誤,這樣賦值會讓原來的普通指針 p 指向被 const 修飾的變量
/*
正確寫法:
int a = 20;
const int *p = &a;
cosnt int **p1 = &p;
*/int *const *p2 = &p;
int **const p3 = &p;

左值引用和右值引用

int main() {int a = 10;    // 左值,有地址有名字,值可以修改int &b = a;int &&c = 20;    // 20 為右值,沒內存,沒名字c = 30// 右值引用可以修改const int &b = 20;/*int temp = 20;temp -> b*/const int &d = 20;return 0;
}

右值引用:

  • int &&c = 20;專門用來引用右值類型,指令上可以自動產生臨時量,然后直接引用臨時量。

  • 右值引用變量本身是一個左值,只能用左值引用來引用它。

  • 不能用一個右值引用變量引用一個左值。

const、指針和引用的結合應用

int main() {// 寫一句代碼,在內存的 0x0018ff44 處寫一個 4 字節的 10int *p = (int *)0x0018ff44;int *&&p = (int *)0x0018ff44;int *const &p = (int *)0x0018ff44;return 0;
}

深入理解 c++ 的 new 和 delete

new 和 delete 為C++ 的運算符

malloc 和 free 為 C 的庫函數

開辟內存失敗時:

  • malloc 需要返回值與 nullptr 比較,為空時失敗。

  • new 會拋異常。

new 有多少種?

int *p1 = new int(20);
int *p2 = new (nothrow) int;
int *p3 = new const int(40);// 定位 new
int data = 0;
int *p4 = new (&data) int(50);
cout << "data: " << data << endl;    // 輸出 data: 0

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

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

相關文章

AI PPT探秘

—— 序言 ——AI時代已經深入到我們的生活、工作之中&#xff0c;AI不會淘汰所有的人&#xff0c;但會淘汰不會用AI的人&#xff0c;讓AI處理執行&#xff0c;你專注決策&#xff01;—— 典型的四步AI PPT過程 ——AI PPT四步&#xff1a;內容——>排版——>美化——&g…

Gin Web 服務集成 Consul:從服務注冊到服務發現實踐指南(下)

在微服務架構中&#xff0c;Web 層作為系統的入口門面&#xff0c;承擔著請求路由、權限校驗和服務聚合等核心功能。本文將圍繞 Gin 框架與 Consul 注冊中心的集成展開&#xff0c;詳細講解 Web 服務如何實現服務注冊與發現&#xff0c;幫助你構建可擴展的微服務前端架構。 承接…

PDF 的開發工具庫: Adobe PDF Library

Adobe PDF Library 是 Adobe 公司提供的一個軟件開發工具包(SDK)&#xff0c;它本質上是 Adobe Acrobat 的"無界面"版本&#xff0c;但功能更為強大。作為 PDF 處理領域的專業解決方案&#xff0c;它為開發者提供了創建、操作和管理 PDF 文檔的全面能力。 #mermaid-s…

dubbo源碼學習2-dubbo協議源碼分析

協議(Protocol)的概念 協議(Protocol)是指在計算機通信或網絡交互中&#xff0c;雙方事先約定好的規則和標準&#xff0c;用于規范數據如何打包、傳輸、接收和解釋。 所以簡單說就是規則&#xff0c;發送數據編碼的規則&#xff0c;接收數據解碼的規則 Dubbo中的協議 在Dubbo…

麒麟信安聯合申威:共筑安全高效的自主計算新生態

為深化長三角區域先進技術產業協同創新&#xff0c;推動集成電路領域技術需求對接&#xff0c;6月26日“集成電路領域產業技術需求對接一申威生態成果分享”專題活動舉行。本次活動聚焦國產化全棧能力建設&#xff0c;重點發布申威產品與生態的最新進展&#xff0c;促成“芯片-…

裸倉庫 + Git Bash 搭建 本地 Git 服務端與客戶端

下面是在 Windows 上使用 裸倉庫 Git Bash 搭建 本地 Git 服務端與客戶端 的詳細步驟。適合本機或局域網其他設備通過 SSH 或本地路徑 訪問&#xff0c;簡單輕量&#xff0c;適合開發者日常使用或小團隊協作。 &#x1f6e0;? 一、準備工作 1. 安裝 Git for Windows 默認安裝…

AI文檔智能體上線!AutoHub v0.7.0 全面升級,重構知識工作流

AI文檔智能體上線&#xff01;AutoHub v0.7.0 全面升級&#xff0c;重構知識工作流 如何讓每一個知識工作者都像專家一樣高效&#xff1f; 這正是 OpenCSG AutoHub 想解決的問題。 無論你是產品經理、項目負責人、運維工程師&#xff0c;還是企業管理者&#xff0c;日常都要…

SpringMVC參數接收與數據返回詳解

一&#xff0c;參數的接收參數接收的幾種方式&#xff1a;1.使用servlet API接收參數在方法參數中添加HttpServletRequest類型的參數&#xff0c;然后就可以像servlet的方法一樣來接收參數 RequestMapping("p1")public String param1(HttpServletRequest request){St…

OpenCV 人臉分析----人臉識別的一個經典類cv::face::EigenFaceRecognizer

操作系統&#xff1a;ubuntu22.04 OpenCV版本&#xff1a;OpenCV4.9 IDE:Visual Studio Code 編程語言&#xff1a;C11 算法描述 這是基于 PCA&#xff08;主成分分析&#xff09; 的人臉識別算法實現。它通過將人臉圖像投影到一個低維的“特征臉”空間中進行識別&#xff0c…

RESTful風格

帶著問題&#xff0c;找答案&#xff1a; 通過本片文章&#xff0c;你會了解以下四點。并且我會給出go語言的實現案例。 1、了解restful風格的來源、起源、演變史 2、了解restful風格的定義、含義 3、掌握restful風格的簡單運用 4、做一個小demo 在restful中前進&#xf…

了解GC嗎?什么是GC?

GC是什么&#xff1f;為什么要GC&#xff1f; GC&#xff08; Garbage Collection &#xff09;&#xff0c;垃圾回收&#xff0c;是Java與C的主要區別之一。作為Java開發者&#xff0c;一般不需要專門編寫內存回收和垃圾清理代碼。這是因為在Java虛擬機中&#xff0c;存在自動…

FDMA讀寫AXI BRAM交互:FPGA高速數據傳輸的核心技術

在圖像處理系統中,當1080P視頻流以每秒60幀的速度傳輸時,傳統DMA每幀會浪費27%的帶寬在地址管理上——而FDMA技術能將這些損失降至3%以內 現代FPGA系統中,高效數據搬運往往是性能瓶頸的關鍵所在。當你在手機上流暢播放4K視頻、在自動駕駛系統中實時處理激光雷達點云時,背后…

獨立開發A/B測試實用教程

A/B測試&#xff08;A/B Testing&#xff09;&#xff0c;又稱分組測試、對照實驗&#xff0c;是產品開發和運營中提升轉化率、優化用戶體驗的常用方法。無論你是做App、SaaS、網站還是小程序&#xff0c;合理地利用A/B測試&#xff0c;都能幫助你用數據驅動決策&#xff0c;讓…

如何將iPhone備份到Mac/MacBook

許多iPhone用戶非常重視備份&#xff0c;但在Mac上選擇合適的備份方法可能會令人困惑。市場上有各種各樣的備份工具&#xff0c;找到一個既易于使用又能保存所有重要數據&#xff08;如照片、視頻、消息、WhatsApp聊天記錄和聯系人&#xff09;的工具至關重要。如果你正在尋找一…

Logseq 插件開發實戰四:發布到官方插件市場

&#x1f6a9;系列回顧 初識插件機制并實現自動壓縮粘貼的圖片國際化 I18N 與配置多語言自定義斜線命令 SlashCommand發布到官方插件市場 開源地址&#xff1a;logseq-plugin-image-tiny&#xff0c;歡迎來?。 &#x1f41e; 插件上線問題記錄 問題描述 本地插件開發完成后…

[netty5: ByteToMessageCodec MessageToByteEncoder ByteToMessageDecoder]-源碼分析

ByteToMessageCodec ByteToMessageCodec 是一個結合了 ByteToMessageDecoder 和 MessageToByteEncoder 的編解碼器&#xff0c;可以實時地將字節流編碼或解碼為消息&#xff0c;反之亦然。 public abstract class ByteToMessageCodec<I> extends ChannelHandlerAdapter {…

Ubuntu20.04安裝mujoco210, mujoco-py時的報錯處理

參考 Ubantu 20.04 安裝 Mujoco210、mujoco-py、gym及報錯解決 安裝 mujoco210 創建 .mujoco 文件夾 mkdir ~/.mujoco親測必須是 .mujoco 文件夾&#xff0c;不然會報錯&#xff01; 下載 mujoco210-linux-x86_64.tar.gz 并解壓到 .mujoco 文件夾 mojoco下載地址 測試 mojo…

全志T507 音頻ALSA核心層注冊流程分析

一.ALSA核心層注冊流程分析 驅動目錄&#xff1a;kernel-4.9/sound/core/sound.c struct file_operations snd_fops {.owner THIS_MODULE,.open snd_open, (inode, file)---->struct snd_minor *mptr snd_minors[minor];---->file->f_op fops_get(mptr->f_ops…

評論區實現 前端Vue

根據后端部分定義評論區功能實現 golang后端部分-CSDN博客&#xff0c;重點需要實現三個部分&#xff0c;1.當前用戶發起新根評論請求&#xff1b;2.評論區展示部分&#xff1b;3.某一根評論的子評論展示以及回復組件顯示。 整體流程解釋 數據從后端接收&#xff0c;整體在in…

差分定位技術:原理、分類與應用場景

文章目錄 簡介基本概念位置差分偽距差分載波相位 差分定位技術精密單點定位&#xff08;PPP&#xff09;差分全球定位系統&#xff08;DGPS&#xff09;實時動態定位&#xff08;RTK&#xff09; 應用場景總結 簡介 差分定位&#xff08;Differential Positioning&#xff09;是…