文章目錄
- 111. 談談atomic
- 1. 什么是原子操作?
- 2. std::atomic 的基本使用
- 示例:基本使用
- 3. 原子操作方法
- 4. 內存模型與順序一致性
- 112. 引用成員變量是否占空間?
- 1. 引用成員變量的定義
- 2. 內存占用情況
- 1. 成員變量的實際占用
- 2. 類的總大小
- 代碼分析
- 113. C++中深拷貝和淺拷貝的區別,什么情況用淺拷貝什么情況用深拷貝,實際編碼中使用過嗎,遇到過什么問題么?
- 淺拷貝的使用場景:
- 涉及指針的淺拷貝
- 深拷貝的使用場景:
- 實際編碼中的問題
- 如何避免問題
- 114. 視頻幀數據格式轉換怎么做?
- 常見視頻幀格式
- 針對RGB
- 針對YUV
- 什么時候需要轉換
- 進行格式轉換的方法
- 1. 手動計算像素轉換:
- 示例代碼:YUV420 轉 RGB24 (這代碼簡單了解一下思路即可)
- 2. 使用現成的圖像處理庫:
- OpenCV:
- FFmpeg:
- 115. RGB 和 YUV 有什么區別,為什么用 YUV?
- 為什么要使用YUV?
111. 談談atomic

1. 什么是原子操作?

2. std::atomic 的基本使用
C++11 引入了 std::atomic 模板類,用于提供對原子類型的支持。std::atomic 可以包裝基本類型(如 int、bool、char 等)和指針類型,使其成為原子類型。
示例:基本使用
#include <iostream>
#include <atomic>
#include <thread>
#include <vector>std::atomic<int> counter(0); // 定義一個原子整型變量void increment(int n) {for (int i = 0; i < n; ++i) {// fetch_add 是 std::atomic 提供的一個成員函數,它會原子地將 counter 增加 1,并返回更新前的值。fetch_add 確保了增加操作是原子的,即在多線程環境中不會出現數據競爭。counter.fetch_add(1); // 使用 fetch_add 原子地增加計數器// counter = counter + 1;// counter++;}
}int main() {const int numThreads = 10;const int incrementsPerThread = 1000;std::vector<std::thread> threads;// 創建多個線程,每個線程執行 increment 函數for (int i = 0; i < numThreads; ++i) {threads.emplace_back(increment, incrementsPerThread);}// 等待所有線程完成for (auto& t : threads) {t.join();}std::cout << "最終計數器的值是: " << counter << std::endl; // 輸出計數器的最終值return 0;
}


3. 原子操作方法

4. 內存模型與順序一致性


112. 引用成員變量是否占空間?
在 C++ 中,引用成員變量是占用空間的,但其空間占用方式和普通成員變量略有不同。
為了更詳細地解釋,我們需要先了解一些基本概念:
1. 引用成員變量的定義
引用成員變量是類成員中使用引用類型的變量。例如:
class MyClass {
public:int x;int& ref;MyClass(int& r) : x(0), ref(r) {} // 引用成員變量的初始化
};
2. 內存占用情況
1. 成員變量的實際占用

2. 類的總大小
類的總內存大小由類中所有成員變量的大小決定,包括引用成員變量。雖然引用本身不占用額外的內存(其實際內存占用與指針相似),但它會導致類的布局和對齊要求。
#include <iostream>
#include <iomanip>class MyClass {
public:int x; int& ref; MyClass(int& r) : x(0), ref(r) {}
};int main() {int a = 10;MyClass obj(a);std::cout << "Size of int: " << sizeof(int) << " bytes" << std::endl;std::cout << "Size of MyClass: " << sizeof(MyClass) << " bytes" << std::endl;std::cout << "Size of reference: " << sizeof(obj.ref) << " bytes" << std::endl;return 0;
}
代碼分析
“引用本身不占內存” 是指引用只是一個已存在對象的別名,而不需要額外的內存空間來存儲其自身的值




113. C++中深拷貝和淺拷貝的區別,什么情況用淺拷貝什么情況用深拷貝,實際編碼中使用過嗎,遇到過什么問題么?
在C++中,深拷貝和淺拷貝是對象拷貝的兩種方式,它們的主要區別在于對指針成員的處理。


淺拷貝的使用場景:
淺拷貝適合于對象不涉及動態內存分配或指針成員時,或多個對象可以安全地共享同一塊內存的情況。一般來說,淺拷貝多用于內置類型和簡單數據類型的復制。
struct Point {int x, y;
};Point p1 = {1, 2};
Point p2 = p1; // 淺拷貝:只復制成員值 //復制 p1 的成員值到 p2 中,而不是地址
//各位一定要注意:這里是將p1的值復制給了p2 ,但是p1和p2并不是同一個對象。
//也就是說,你可以將淺拷貝分為兩個部分: 一個部分是簡單類型的值拷貝,另外一個是含有指針的復制
涉及指針的淺拷貝
淺拷貝通常指的是當對象內部有指針成員時,拷貝對象時只復制了指針的地址,而沒有復制指針指向的實際數據。
class ShallowCopyExample {
public:int* data;ShallowCopyExample(int value) {data = new int(value); // 動態分配內存}~ShallowCopyExample() {delete data; // 釋放內存}
};int main() {ShallowCopyExample obj1(10);ShallowCopyExample obj2 = obj1; // 淺拷貝,只拷貝指針地址std::cout << obj1.data << std::endl; // 輸出指針的地址std::cout << obj2.data << std::endl; // 輸出相同的地址(共享同一塊內存)
}

深拷貝的使用場景:

class DeepCopy {
public:int* data;DeepCopy(int value) {data = new int(value); // 動態分配內存}// 自定義拷貝構造函數,實現深拷貝DeepCopy(const DeepCopy& other) {data = new int(*other.data); // 分配新內存,并復制內容}// 自定義賦值操作符,實現深拷貝DeepCopy& operator=(const DeepCopy& other) {if (this == &other) return *this; // 自我賦值檢查delete data; // 釋放舊內存data = new int(*other.data); // 分配新內存并復制內容return *this;}~DeepCopy() {delete data; // 釋放內存}
};int main() {DeepCopy obj1(10);DeepCopy obj2 = obj1; // 深拷貝:obj1 和 obj2 擁有獨立的內存
}
實際編碼中的問題

常見問題示例:
class ShallowCopyExample {
public:int* data;ShallowCopyExample(int value) {data = new int(value);}~ShallowCopyExample() {delete data; // 釋放內存}
};ShallowCopyExample obj1(10);
ShallowCopyExample obj2 = obj1; // 淺拷貝,obj2和obj1共享同一塊內存// 當obj1和obj2銷毀時,都會試圖釋放同一塊內存,導致雙重釋放錯誤
如何避免問題

class DeepCopyWithSmartPointer {
public:std::unique_ptr<int> data;DeepCopyWithSmartPointer(int value) : data(std::make_unique<int>(value)) {}
};
114. 視頻幀數據格式轉換怎么做?
常見視頻幀格式

針對RGB
每個像素信息也都是由不同亮度的RGB信息組合而成。

如果直接使用RGB信號進行圖像信號傳輸,是無法兼容黑白電視,且占用的寬帶成本高。所以將圖像信息分成亮度信息和色度信息進行傳輸,成為了彩色電視傳輸的主要技術。
針對YUV
一個圖像信息分為一個亮度信息和兩個色度信息,亮度信息用Y表示,色相和飽和度信息用UV表示,這就是目前主流的YUV顏色空間。

什么時候需要轉換
YUV 轉 RGB:當視頻數據從編碼器傳遞給顯示設備時,通常需要從 YUV 轉換為 RGB。
RGB 轉 YUV:在進行視頻壓縮時,RGB 數據通常需要轉換為 YUV 格式。
進行格式轉換的方法
1. 手動計算像素轉換:

示例代碼:YUV420 轉 RGB24 (這代碼簡單了解一下思路即可)
void YUV420ToRGB24(unsigned char* yuvBuffer, unsigned char* rgbBuffer, int width, int height) {int frameSize = width * height;int uOffset = frameSize;int vOffset = frameSize + frameSize / 4;for (int j = 0; j < height; j++) {for (int i = 0; i < width; i++) {int yIndex = j * width + i;int uIndex = (j / 2) * (width / 2) + (i / 2);int vIndex = (j / 2) * (width / 2) + (i / 2);int Y = yuvBuffer[yIndex];int U = yuvBuffer[uOffset + uIndex] - 128;int V = yuvBuffer[vOffset + vIndex] - 128;int R = Y + 1.402 * V;int G = Y - 0.344136 * U - 0.714136 * V;int B = Y + 1.772 * U;R = R < 0 ? 0 : (R > 255 ? 255 : R);G = G < 0 ? 0 : (G > 255 ? 255 : G);B = B < 0 ? 0 : (B > 255 ? 255 : B);int rgbIndex = yIndex * 3;rgbBuffer[rgbIndex] = (unsigned char)R;rgbBuffer[rgbIndex + 1] = (unsigned char)G;rgbBuffer[rgbIndex + 2] = (unsigned char)B;}}
}
2. 使用現成的圖像處理庫:
大多數情況下,我們不需要自己編寫格式轉換的代碼,現有的庫已經高效地實現了這些功能。
OpenCV:
OpenCV 提供了圖像和視頻處理的多種工具,其中包括各種格式轉換功能。使用 OpenCV,可以簡單地完成格式轉換,例如從 YUV 轉 RGB。
#include <opencv2/opencv.hpp>int main() {cv::Mat yuvFrame; // 假設這是一個 YUV 格式的視頻幀cv::Mat rgbFrame;// 將 YUV 格式轉換為 RGB 格式cv::cvtColor(yuvFrame, rgbFrame, cv::COLOR_YUV2RGB);// 現在 rgbFrame 中存儲的就是 RGB 格式的數據return 0;
}
FFmpeg:
FFmpeg 是一個強大的多媒體處理庫,支持各種視頻格式的轉換。可以通過它的 API 或命令行工具完成視頻幀格式轉換。
使用 FFmpeg 命令行工具,將 YUV 轉換為 RGB:
ffmpeg -i input.yuv -pix_fmt rgb24 output.rgb
115. RGB 和 YUV 有什么區別,為什么用 YUV?


為什么要使用YUV?

之后我會持續更新,如果喜歡我的文章,請記得一鍵三連哦,點贊關注收藏,你的每一個贊每一份關注每一次收藏都將是我前進路上的無限動力 !!!↖(▔▽▔)↗感謝支持!