嵌入式面試高頻(5)!!!C++語言(嵌入式八股文,嵌入式面經)

C++有幾種傳值方式之間的區別

一、值傳遞(Pass by Value)

  • 機制:創建參數的副本,函數內操作不影響原始數據
  • 語法void func(int x)
  • 特點
    • 數據安全:原始數據不受影響
    • 性能開銷:需要復制大對象(如結構體、類)
    • 示例
void increment(int x) { x++; } // 修改副本,不影響原始值
int a = 10;
increment(a); // a仍為10引用高效移動資源

?

二、指針傳遞(Pass by Pointer)

  • 機制:傳遞變量的地址,函數通過指針間接操作原始數據
  • 語法void func(int* ptr)
  • 特點
    • 可修改原始數據:通過*ptr修改
    • 空指針風險:需檢查ptr != nullptr
    • 示例
void increment(int* ptr) { if (ptr) (*ptr)++; // 安全檢查
}
int a = 10;
increment(&a); // a變為11

?

三、引用傳遞(Pass by Reference)

  • 機制:傳遞變量的別名,函數直接操作原始數據
  • 語法void func(int& ref)
  • 特點
    • 可修改原始數據:直接操作引用
    • 安全性:引用必須初始化,無空引用
    • 示例
void increment(int& ref) { ref++; } // 直接操作原始值
int a = 10;
increment(a); // a變為11

?

四、核心區別對比

特性值傳遞指針傳遞引用傳遞
操作對象副本原始數據(通過地址)原始數據(通過別名)
是否修改原值
語法復雜度簡單(直接傳值)較復雜(需解引用)簡單(類似值傳遞)
空值風險有空指針風險無(必須初始化)
典型用途簡單數據、只讀操作需顯式傳遞地址、可空對象參數、避免拷貝

五、示例對比?

// 值傳遞
void passByValue(int val) { val = 20; } // 不影響原始值// 指針傳遞
void passByPointer(int* ptr) { if (ptr) *ptr = 20; // 需檢查空指針
}// 引用傳遞
void passByReference(int& ref) { ref = 20; } // 直接修改int main() {int x = 10;passByValue(x);     // x仍為10passByPointer(&x);  // x變為20passByReference(x); // x變為20return 0;
}

?

六、C++11 新增:右值引用(Move Semantics)

  • 機制:專門處理臨時對象(右值)的引用,避免深拷貝
  • 語法void func(Type&& rvalue)
  • 典型用途:移動構造函數、移動賦值運算符
  • 示例
std::vector<int> createVector() {return std::vector<int>{1,2,3};
}std::vector<int> vec = createVector(); // 通過右值引用高效移動資源

?二.數組指針與指針數組的區別

一、核心區別

特性數組指針(Pointer to Array)指針數組(Array of Pointers)
本質指針:指向一個數組數組:存儲多個指針
語法int (*ptr)[5];(括號強制 ptr 為指針)int* arr[5];(arr 先與 [] 結合為數組)
指向對象整個數組數組的元素(每個元素是一個指針)
指針運算ptr + 1?跳過整個數組(如 5 個 int)arr + 1?指向下一個元素(下一個指針)
典型用途傳遞多維數組、精確控制內存布局管理多個動態分配的對象、字符串數組

二、語法對比

1.?數組指針(指向數組的指針)?

int arr[5] = {1,2,3,4,5};
int (*ptr)[5] = &arr;  // 指向包含5個int的數組// 訪問元素
(*ptr)[0] = 10;  // 修改arr[0]為10

2.?指針數組(包含指針的數組)?

?

int a = 1, b = 2, c = 3;
int* arr[3] = {&a, &b, &c};  // 數組的每個元素是int*// 訪問元素
*arr[0] = 10;  // 修改a為10

?三、內存布局差異

1.?數組指針?

ptr ──> [1, 2, 3, 4, 5]  // 指向整個數組

?

  • ptr?存儲整個數組的起始地址
  • sizeof(ptr)?為指針大小(通常 4/8 字節)

2.?指針數組?

arr ──> [&a, &b, &c]     // 數組元素為指針│    │    │▼    ▼    ▼a    b    c

?

  • arr?是一個數組,包含多個指針
  • sizeof(arr)?為?3 * sizeof(int*)

四、典型應用場景

1.?數組指針的應用
// 傳遞多維數組
void printMatrix(int (*matrix)[4], int rows) {for (int i = 0; i < rows; i++) {for (int j = 0; j < 4; j++) {printf("%d ", matrix[i][j]);}printf("\n");}
}int main() {int matrix[3][4] = {...};printMatrix(matrix, 3);  // matrix退化為int (*)[4]
}

?2.?指針數組的應用

// 字符串數組
const char* fruits[3] = {"Apple","Banana","Cherry"
};// 動態內存管理
int* ptrs[5];
for (int i = 0; i < 5; i++) {ptrs[i] = new int(i);
}

?

五、常見混淆點

1.?括號位置決定類型

?

int (*ptr)[5];  // 數組指針:ptr是指向包含5個int的數組的指針
int* ptr[5];    // 指針數組:ptr是包含5個int*的數組
2.?數組名 vs 數組指針
int arr[5];
int* ptr1 = arr;      // 指向首元素的指針(隱式轉換)
int (*ptr2)[5] = &arr; // 指向整個數組的指針printf("%p\n", arr);     // 數組首元素地址
printf("%p\n", &arr);    // 整個數組的地址(數值相同,但類型不同)
printf("%p\n", arr + 1); // 跳過1個元素
printf("%p\n", &arr + 1); // 跳過整個數組(5個元素)

?三.指針函數與函數指針的區別

一、核心區別

特性指針函數(Function Returning Pointer)函數指針(Pointer to Function)
本質函數:返回值為指針類型指針:指向一個函數
語法int* func(int a);(返回 int*)int (*ptr)(int a);(ptr 為指針)
用途返回動態分配的內存或全局變量地址作為參數傳遞函數、實現回調機制
調用方式int* result = func(10);int val = (*ptr)(10);?或?ptr(10);

?

二、語法對比

1.?指針函數(返回指針的函數)
int* createArray(int size) {int* arr = new int[size];for (int i = 0; i < size; i++) {arr[i] = i;}return arr;  // 返回動態分配的數組指針
}// 調用
int* ptr = createArray(5);
2.?函數指針(指向函數的指針)
int add(int a, int b) { return a + b; }// 定義函數指針并初始化
int (*op)(int, int) = add;// 調用方式1
int result = (*op)(3, 4);  // 顯式解引用// 調用方式2(C++允許隱式解引用)
int result2 = op(3, 4);    // 等價于上一行

?

三、典型應用場景

1.?指針函數的應用
// 返回靜態變量的地址
const char* getMessage() {static const char* msg = "Hello";return msg;
}

?2.?函數指針的應用

// 回調函數示例
void process(int a, int b, int (*func)(int, int)) {int result = func(a, b);printf("Result: %d\n", result);
}int main() {int (*add)(int, int) = [](int a, int b) { return a + b; };process(3, 4, add);  // 輸出7
}

?

四、常見混淆點

1.?括號位置決定類型
int* func(int a);  // 指針函數:返回int*
int (*ptr)(int a); // 函數指針:ptr指向返回int的函數

?2.?函數指針作為參數

// 排序函數接受比較函數指針
void sort(int* arr, int size, bool (*compare)(int, int)) {// 排序邏輯...
}bool ascending(int a, int b) { return a < b; }// 調用
sort(array, 10, ascending);

?四.malloc和calloc的區別

?

一、核心區別

特性malloccalloc
初始化不初始化分配的內存(內容隨機)將內存初始化為 0
參數單個參數:所需內存字節數兩個參數:元素數量和元素大小
原型void* malloc(size_t size);void* calloc(size_t num, size_t size);
性能略快(無需初始化)略慢(需清零內存)

二、示例對比

1.?malloc 的使用

?

int* ptr = (int*)malloc(5 * sizeof(int));  // 分配5個int的內存
if (ptr != NULL) {// 內存內容未初始化,可能包含隨機值for (int i = 0; i < 5; i++) {printf("%d ", ptr[i]);  // 輸出隨機值}
}
2.?calloc 的使用
int* ptr = (int*)calloc(5, sizeof(int));  // 分配5個int的內存并初始化為0
if (ptr != NULL) {// 內存內容已初始化為0for (int i = 0; i < 5; i++) {printf("%d ", ptr[i]);  // 輸出: 0 0 0 0 0}
}

?三、內存布局差異

?

// malloc分配的內存(未初始化)
ptr ──> [隨機值][隨機值][隨機值][隨機值][隨機值]// calloc分配的內存(初始化為0)
ptr ──> [0][0][0][0][0]

四、安全與性能考量

  1. 安全性

    • calloc適合需要初始化的場景(如存儲結構體、數組)
    • malloc需手動初始化(如使用memset):
int* ptr = malloc(5 * sizeof(int));
memset(ptr, 0, 5 * sizeof(int));  // 手動清零

?

  1. 性能calloc因初始化操作會稍慢

    • 大數據塊初始化可能影響性能

五、典型應用場景

場景推薦函數原因
存儲需要初始化的數據calloc自動清零,避免未定義行為
存儲無需初始化的數據malloc略高效
分配二進制緩沖區malloc后續會寫入數據,無需提前初始化
分配結構體數組calloc確保結構體成員初始化為有效值

?五.內存泄漏,如何檢測和避免?

一、什么是內存泄漏?

  • 定義:程序動態分配的內存(如malloc/new)未被正確釋放(如free/delete),導致這部分內存永久無法被回收
  • 危害
    • 隨著程序運行,可用內存逐漸減少
    • 最終導致系統性能下降、程序崩潰或系統崩潰

二、內存泄漏的常見原因

  1. 忘記釋放內存

?

void func() {int* ptr = new int[100];  // 分配內存// 忘記調用delete[] ptr;
}

異常導致路徑未釋放

void func() {int* ptr = new int[100];if (condition) {throw std::exception();  // 異常退出,未釋放內存}delete[] ptr;
}

?指針覆蓋

int* ptr = new int;
ptr = new int;  // 原內存丟失,無法釋放

?循環分配內存

while (true) {int* ptr = new int[1000];  // 持續分配,無釋放
}

?類中未定義析構函數

class Resource {
public:Resource() { data = new int[100]; }// 未定義析構函數釋放data
private:int* data;
};

?

三、檢測內存泄漏的方法

1.?靜態代碼分析工具
  • 工具:Cppcheck、Clang-Tidy、PC-Lint
  • 特點
    • 不運行程序,直接分析代碼
    • 檢測常見模式(如分配后未釋放)
  • 示例命令

cppcheck --enable=all --inconclusive your_file.cpp

2.?動態內存分析工具
  • Valgrind(Linux)

  • valgrind --leak-check=full ./your_program

?

四、避免內存泄漏的最佳實踐

1.?RAII(資源獲取即初始化)原則
  • 使用智能指針(C++):

    cpp

    運行

    #include <memory>void func() {std::unique_ptr<int[]> ptr(new int[100]);  // 自動釋放// 無需手動delete
    }
    
2.?容器替代原始數組

cpp

運行

#include <vector>void func() {std::vector<int> data(100);  // 自動管理內存
}
3.?異常安全
  • 使用try-catch確保資源釋放:

    cpp

    運行

    void func() {int* ptr = new int[100];try {// 可能拋出異常的代碼} catch (...) {delete[] ptr;throw;}delete[] ptr;
    }
    
4.?遵循配對原則
  • malloc?→?free
  • new?→?delete
  • new[]?→?delete[]
5.?避免指針淺拷貝
  • 使用深拷貝或禁用拷貝構造函數
  • 使用智能指針的移動語義
6.?代碼審查
  • 重點檢查:
    • 長時間運行的程序(如服務器)
    • 循環中的內存分配
    • 復雜函數中的多條返回路徑

五、高級技術

1.?內存池(Memory Pool)
  • 預先分配大塊內存,按需分配小塊,減少系統調用
  • 避免頻繁分配 / 釋放導致的碎片
2.?智能指針的使用場景
類型用途
std::unique_ptr獨占所有權
std::shared_ptr共享所有權(引用計數)
std::weak_ptr弱引用,避免循環引用

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

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

相關文章

Spark 之 AQE

個人其他鏈接 AQE 執行順序https://blog.csdn.net/zhixingheyi_tian/article/details/125112793 AQE 產生 AQE 的 循環觸發點 src/main/scala/org/apache/spark/sql/execution/adaptive/AdaptiveSparkPlanExec.scala override def doExecute(): RDD[InternalRow] = {withFin…

FSMC擴展外部SRAM

提示&#xff1a;文章 文章目錄 前言一、背景二、2.12.2 三、3.1 總結 前言 前期疑問&#xff1a; 本文目標&#xff1a; 一、背景 2025年6月7日 19:34:48 今天看了FSMC擴展外部SRAM的文章&#xff0c;大概理解到stm32除了內部存儲器&#xff0c;還可以擴展外部存儲器。其中s…

【CSS-6】深入理解CSS復合選擇器:提升樣式表的精確性與效率

CSS選擇器是前端開發的基石&#xff0c;而復合選擇器則是其中最強大且實用的工具之一。本文將全面解析CSS復合選擇器的類型、用法、優先級規則以及最佳實踐&#xff0c;幫助你編寫更高效、更精確的樣式表。 1. 什么是復合選擇器&#xff1f; 復合選擇器是通過組合多個簡單選擇…

使用python實現奔跑的線條效果

效果&#xff0c;展示&#xff08;視頻效果展示&#xff09;&#xff1a; 奔跑的線條 from turtle import * import time t1Turtle() t2Turtle() t3Turtle() t1.hideturtle() t2.hideturtle() t3.hideturtle() t1.pencolor("red") t2.pencolor("green") t3…

從零搭建uniapp項目

目錄 創建uni-app項目 基礎架構 安裝 uni-ui 組件庫 安裝sass依賴 easycom配置組件自動導入 配置view等標簽高亮聲明 配置uni-ui組件類型聲明 解決 標簽 錯誤 關于tsconfig.json中提示報錯 關于非原生標簽錯誤&#xff08;看運氣&#xff09; 安裝 uview-plus 組件庫…

Redis主從復制的原理一 之 概述

概述 本文概要性的介紹了Redis主從復制原理&#xff0c;及新舊版本主從復制的區別&#xff0c;優缺點。具體的主從復制過程可詳見「Redis主從復制原理二 之 主從復制工作流程」 舊版主從復制的實現 Redis的復制功能分為 同步&#xff08;sync&#xff09;和 命令傳播&#xff…

網絡原理 4-TCP3

上篇文章&#xff0c;我們講了TCP協議的連接管理&#xff08;”三次握手“和”四次揮手“的過程&#xff09;。 4、滑動窗口 這個滑動窗口是TCP中非常有特點的機制。我們知道&#xff0c;TCP是通過前面講的三個機制&#xff1a;確認應答&#xff0c;超時重傳&#xff0c;連接…

【使用 Loki + Promtail + Grafana 搭建輕量級容器日志分析平臺】

使用 Loki Promtail Grafana 搭建輕量級容器日志分析平臺 摘要 本文介紹如何通過 Docker Compose 快速搭建 Loki 日志存儲、Promtail 日志采集和 Grafana 日志可視化/告警的完整流程。用最小化示例演示核心配置、常見問題排查和告警規則設置&#xff0c;幫助讀者快速上手。…

CRMEB 中 PHP 快遞查詢擴展實現:涵蓋一號通、阿里云、騰訊云

目前已有一號通快遞查詢、阿里云快遞查詢擴展 擴展入口文件 文件目錄 crmeb\services\express\Express.php 默認一號通快遞查詢 namespace crmeb\services\express;use crmeb\basic\BaseManager; use crmeb\services\AccessTokenServeService; use think\Container; use thi…

使用 Python 自動化 Word 文檔樣式復制與內容生成

在辦公自動化領域&#xff0c;如何高效地處理 Word 文檔的樣式和內容復制是一個常見需求。本文將通過一個完整的代碼示例&#xff0c;展示如何利用 Python 的 python-docx 庫實現 Word 文檔樣式的深度復制 和 動態內容生成&#xff0c;并結合知識庫中的最佳實踐優化文檔處理流程…

【MATLAB代碼】基于MCC(最大相關熵)的EKF,一維濾波,用于解決觀測噪聲的異常|附完整代碼,訂閱專欄后可直接查看

本文所述的代碼實現了一種基于最大相關熵準則(Maximum Correntropy Criterion, MCC)的魯棒性卡爾曼濾波算法(MCC-KF),重點解決傳統卡爾曼濾波在觀測噪聲存在異常值時估計精度下降的問題。通過引入高斯核函數對殘差進行加權處理,有效降低了異常觀測值對狀態估計的干擾。訂…

46、web實驗-遍歷數據與頁面bug修改

46、web實驗-遍歷數據與頁面bug修改 在Web開發中&#xff0c;遍歷數據和修改頁面bug是常見的任務。以下是關于這兩個主題的講解&#xff1a; ### 一、遍歷數據 **目的**&#xff1a;在頁面上動態展示數據&#xff0c;例如用戶列表、商品信息等。 **常用方法**&#xff1a; ####…

華為云Flexus+DeepSeek征文|體驗華為云ModelArts快速搭建Dify-LLM應用開發平臺并創建自己的自定義聊天助手

華為云FlexusDeepSeek征文&#xff5c;體驗華為云ModelArts快速搭建Dify-LLM應用開發平臺并創建自己的自定義聊天助手 什么是華為云ModelArts 華為云ModelArts ModelArts是華為云提供的全流程AI開發平臺&#xff0c;覆蓋從數據準備到模型部署的全生命周期管理&#xff0c;幫助…

Qwen大語言模型里,<CLS>屬于特殊的標記:Classification Token

Qwen大語言模型里,<CLS>屬于特殊的標記:Classification Token 目錄 Qwen大語言模型里,<CLS>屬于特殊的標記:Classification Token功能解析工作機制應用場景舉例說明技術要點在自然語言處理(NLP)領域 都是<CLS> + <SEP>嗎?一、CLS和SEP的作用與常見用法1. **CLS標…

R語言AI模型部署方案:精準離線運行詳解

R語言AI模型部署方案:精準離線運行詳解 一、項目概述 本文將構建一個完整的R語言AI部署解決方案,實現鳶尾花分類模型的訓練、保存、離線部署和預測功能。核心特點: 100%離線運行能力自包含環境依賴生產級錯誤處理跨平臺兼容性模型版本管理# 文件結構說明 Iris_AI_Deployme…

JAVA畢業設計224—基于Java+Springboot+vue的家政服務系統(源代碼+數據庫)

畢設所有選題&#xff1a; https://blog.csdn.net/2303_76227485/article/details/131104075 基于JavaSpringbootvue的家政服務系統(源代碼數據庫)224 一、系統介紹 本項目前后端分離&#xff0c;分為用戶、家政人員、管理員三種角色 1、用戶&#xff1a; 登錄、注冊、輪播…

滴滴 服務端 面經

一、緩存與數據庫的使用場景及性能差異 1. 緩存的適用場景 高頻讀、低頻寫場景&#xff1a;如商品詳情頁、用戶信息等讀多寫少的數據&#xff0c;減少數據庫壓力。實時性要求不高的數據&#xff1a;如首頁推薦列表、統計數據&#xff08;非實時更新&#xff09;&#xff0c;允…

linux操作系統---網絡協議

目錄 案例演練----網絡搭建 路由啟配置 多個路由情況下如何聯通 靜態路由 案例演練----網絡搭建 Cisco交換機的命令行用戶模式1 switch> 特權模式1 switch>enable disable回到用戶模式 2 switch#全局配置模式1 switch#config terminal 2 switch(co…

華為OD機試_2025 B卷_計算某個字符出現次數(Python,100分)(附詳細解題思路)

文章目錄 題目描述字符計數解析&#xff1a;簡單高效的統計方法核心解題思路完整代碼實現應用場景擴展 題目描述 寫出一個程序&#xff0c;接受一個由字母、數字和空格組成的字符串&#xff0c;和一個字符&#xff0c;然后輸出"輸入字符串&#xff08;第二行輸入的字符&a…

華為倉頡語言初識:并發編程之同步機制(上)

前言 線程同步機制是多線程下解決線程對共享資源競爭的主要方式&#xff0c;華為倉頡語言提供了三種常見的同步機制用來保證線程同步安全&#xff0c;分別是原子操作&#xff0c;互斥鎖和條件變量。本篇文章詳細介紹主要倉頡語言解決同步機制的方法&#xff0c;建議點贊收藏&a…