C++回顾

平时用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,避免了不必要的拷贝操作。