C++回顾
- 其他
- 2025-03-27
- 170热度
- 0评论
平时用C++比较少,最近项目需要用到C++,现简单再回顾一下。
单例模式
在某些场景下,一个类只需要有一个实例就足够了,例如配置管理类、日志记录器、数据库连接池等。使用单例模式可以避免创建多个实例导致的资源浪费、数据不一致等问题。
单例模式是一种创建型设计模式,它确保一个类只有一个实例,并提供一个全局访问点来获取该实例。在程序运行期间,这个类的实例始终只有一个,所有对该类实例的访问都通过这个全局访问点进行。
#include <iostream>
class Board {
private:
// 私有构造函数,防止外部实例化
Board() {}
// 禁止拷贝构造函数
Board(const Board&) = delete;
// 禁止赋值运算符
Board& operator=(const Board&) = delete;
static Board* instance;
public:
// 静态方法,用于获取唯一实例
static Board& GetInstance() {
if (instance == nullptr) {
instance = new Board();
}
return *instance;
}
void printMessage() {
std::cout << "This is the Board instance." << std::endl;
}
};
// 初始化静态成员变量
Board* Board::instance = nullptr;
int main() {
Board& board = Board::GetInstance();
board.printMessage();
return 0;
}
智能指针
在传统的 C++ 中,使用 new 运算符手动分配内存,需要使用 delete 运算符手动释放内存。如果忘记释放内存,就会导致内存泄漏。使用智能指针可以自动管理对象的生命周期,避免内存泄漏的问题。
std::make_unique 是 C++14 引入的一个函数模板,用于创建 std::unique_ptr 对象。std::unique_ptr 是一种智能指针,它对所指向的对象拥有唯一所有权,即同一时间只能有一个 std::unique_ptr 指向同一个对象。当 std::unique_ptr 被销毁时,它所指向的对象也会被自动销毁。
#include <iostream>
#include <memory>
class MyClass {
public:
MyClass() {
std::cout << "MyClass constructor" << std::endl;
}
~MyClass() {
std::cout << "MyClass destructor" << std::endl;
}
void doSomething() {
std::cout << "Doing something..." << std::endl;
}
};
int main() {
// 使用 std::make_unique 创建 std::unique_ptr
auto ptr = std::make_unique<MyClass>();
ptr->doSomething();
// 当 ptr 离开作用域时,MyClass 对象会自动销毁
return 0;
}
Lambda 表达式
Lambda 表达式的主要优点是简洁性和灵活性。在一些场景下,我们只需要一个简单的函数,而且这个函数只在某个特定的地方使用一次,使用 Lambda 表达式可以避免定义一个单独的命名函数,使代码更加简洁。
Lambda 表达式是 C++11 引入的一种匿名函数机制,它允许在代码中定义一个临时的、没有名称的函数。Lambda 表达式可以捕获外部变量,从而在函数内部使用这些变量。
[capture list] (parameter list) mutable(可选) -> return type(可选) { function body }
实例,lambda一般用于设置回调函数。
codec->OnInputReady([this, codec]() {
// 捕获列表 [this, codec] 表示捕获当前对象和 codec 变量
xEventGroupSetBitsFromISR(...);
return ...;
});
移动语义std::move
在某些情况下,对象的拷贝操作可能会非常昂贵,例如对象包含大量的数据或者动态分配的内存。使用移动语义可以避免这些不必要的拷贝操作,提高程序的性能。
移动语义是 C++11 引入的一个重要特性,它允许将对象的资源所有权从一个对象转移到另一个对象,避免不必要的拷贝操作。std::move 是一个标准库函数,用于将左值转换为右值引用,从而触发移动构造函数或移动赋值运算符。
#include <iostream>
#include <vector>
class MyVector {
private:
std::vector<int> data;
public:
MyVector(const std::vector<int>& vec) : data(vec) {
std::cout << \"Copy constructor called\" << std::endl;
}
// 移动构造函数
MyVector(MyVector&& other) noexcept : data(std::move(other.data)) {
std::cout << \"Move constructor called\" << std::endl;
}
void printSize() {
std::cout << \"Size: \" << data.size() << std::endl;
}
};
int main() {
std::vector<int> vec = {1, 2, 3, 4, 5};
MyVector v1(vec);
// 使用 std::move 调用移动构造函数
MyVector v2(std::move(v1));
v2.printSize();
return 0;
}
在上述代码中,std::move(v1) 将 v1 转换为右值引用,从而调用 MyVector 的移动构造函数。移动构造函数将 v1 的 data 资源所有权转移到 v2,避免了不必要的拷贝操作。
模版
C++ 模板(Template)是一种强大的编程特性,它允许你编写泛型代码,使得代码能够在不同数据类型上重复使用。模板支持函数模板和类模板,它们能在编译时根据具体类型生成代码,从而提高代码的复用性和灵活性。
函数模版
#include <iostream>
using namespace std;
template <typename T>
T add(T a, T b) {
return a + b;
}
//template <typename T>:这是函数模板的声明。T 是类型参数,表示函数可以处理任何类型。
//T add(T a, T b):定义了一个接受两个 T 类型参数并返回一个 T 类型结果的函数。
int main() {
cout << add(3, 5) << endl; // 调用模板函数,类型为 int
cout << add(3.5, 5.5) << endl; // 调用模板函数,类型为 double
return 0;
}
类模版
#include <iostream>
using namespace std;
template <typename T>
class Box {
private:
T value;
public:
void setValue(T v) { value = v; }
T getValue() { return value; }
};
//template <typename T>:定义类模板,T 是类型参数。
//T value:类中的成员变量 value 是类型 T。
//setValue(T v) 和 getValue():成员函数也使用模板类型 T。
int main() {
Box<int> intBox;
intBox.setValue(5);
cout << intBox.getValue() << endl; // 输出:5
Box<double> doubleBox;
doubleBox.setValue(3.14);
cout << doubleBox.getValue() << endl; // 输出:3.14
return 0;
}