文章目录
- 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?

之后我会持续更新,如果喜欢我的文章,请记得一键三连哦,点赞关注收藏,你的每一个赞每一份关注每一次收藏都将是我前进路上的无限动力 !!!↖(▔▽▔)↗感谢支持!