代码随想录八股训练营第三十九天| C++

前言

一、说一下 lambda函数?

1.1.Lambda 函数的一般语法如下:

1.2.捕获子句:

二、C++ 怎么实现一个单例模式?

2.1.懒汉式(线程不安全):

2.2.饿汉式(线程安全):

2.3.双重检查锁定(线程安全):

2.4.单例模式的变体:使用 std::call_once(C++11):

总结


前言

在现代软件开发中,设计模式是解决常见问题的一种可重用方案。单例模式是其中的一种模式,它确保一个类只有一个实例,并提供一个全局访问点。此外,Lambda 函数在 C++11 及更高版本中提供了一种编写匿名函数的便捷方式,它们在需要简短函数对象时非常有用。


一、说一下 lambda函数?

在 C++ 中,lambda 函数(也称为 lambda 表达式)是一种便捷的匿名函数定义方式,它允许你在不定义传统函数的情况下创建函数对象。Lambda 函数在 C++11 标准中被引入,并且成为了 C++14 和 C++17 标准的一部分。Lambda 函数通常用于简短的操作,或者作为参数传递给函数,特别是那些接受函数对象作为参数的算法,如 std::sortstd::for_each 等。

1.1.Lambda 函数的一般语法如下:

  • capture:捕获子句,用于指定 lambda 函数可以从封闭作用域中捕获哪些变量。可以是值捕获(通过复制)、引用捕获(通过引用)或默认捕获(通过值或引用,取决于变量的类型)。
  • parameters:参数列表,与普通函数参数列表类似。
  • return_type:返回类型,如果 lambda 函数体中包含单一的返回语句,可以省略返回类型。
  • function body:函数体,包含 lambda 函数的代码。
[capture] (parameters) -> return_type {
    // function body
}

1.2.捕获子句:

  • 值捕获:使用等号 = 后跟要捕获的变量列表。
  • 引用捕获:使用 & 后跟要捕获的变量列表。
  • 混合捕获:可以同时使用值捕获和引用捕获。
  • 默认捕获:不写捕获子句时,默认不捕获任何变量。
#include <iostream>
#include <vector>
#include <algorithm>

int main() {
    std::vector<int> nums = {1, 2, 3, 4, 5};

    // 使用 lambda 表达式对向量进行排序
    std::sort(nums.begin(), nums.end(), [](int a, int b) {
        return a > b; // 降序排序
    });

    // 使用 lambda 表达式打印向量中的元素
    std::for_each(nums.begin(), nums.end(), [](int n) {
        std::cout << n << " ";
    });

    return 0;
}
//值捕获(Value Capture)
//在值捕获中,lambda 函数内部的变量是外部变量的副本。任何对这些变量的修改都不会影响原始变量。
int outer_var = 10;
auto lambda = [outer_var]() {
    std::cout << "Value capture: " << outer_var << std::endl;
    outer_var = 20; // 修改的是副本,不会影响 outer_var
};
std::cout << "Original value: " << outer_var << std::endl; // 输出 10
lambda(); // 输出 Value capture: 10,然后输出 Original value: 10
//引用捕获(Reference Capture)
//在引用捕获中,lambda 函数内部的变量是对外部变量的引用。对这些变量的修改会影响原始变量。
int outer_var = 10;
auto lambda = [&outer_var]() {
    std::cout << "Reference capture: " << outer_var << std::endl;
    outer_var = 20; // 修改的是原始变量
};
std::cout << "Original value: " << outer_var << std::endl; // 输出 20
lambda(); // 输出 Reference capture: 20,然后输出 Original value: 20
//混合捕获(Mixed Capture)
//可以同时使用值捕获和引用捕获。
int value_var = 1;
int& ref_var = value_var;
auto lambda = [value_var, &ref_var]() {
    std::cout << "Mixed capture - value: " << value_var << ", ref: " << ref_var << std::endl;
    value_var = 2;
    ref_var = 3;
};
std::cout << "Original value: " << value_var << ", ref: " << ref_var << std::endl; // 输出 Original value: 1, ref: 1
lambda(); // 输出 Mixed capture - value: 1, ref: 1,然后输出 Original value: 2, ref: 3
//默认捕获(Default Capture)
//如果不指定捕获方式,lambda 函数不会捕获任何外部变量。
int outer_var = 10;
auto lambda = [] {
    std::cout << "Default capture: " << outer_var << std::endl; // 错误:outer_var 在这里未定义
};
// lambda(); // 这将导致编译错误,因为 outer_var 没有被捕获

二、C++ 怎么实现一个单例模式?

单例模式是一种常用的设计模式,它确保一个类只有一个实例,并提供一个全局访问点来获取这个实例。在 C++ 中实现单例模式有多种方法,下面介绍两种常见的实现方式:

2.1.懒汉式(线程不安全):

  • 这种方式在第一次使用时才创建实例,但它不是线程安全的。
class Singleton {
private:
    static Singleton* instance;
    Singleton() {} // 构造函数

public:
    // 禁止拷贝和赋值
    Singleton(const Singleton&) = delete;
    Singleton& operator=(const Singleton&) = delete;

    static Singleton* getInstance() {
        if (instance == nullptr) {
            instance = new Singleton();
        }
        return instance;
    }
};

// 初始化静态成员变量
Singleton* Singleton::instance = nullptr;

2.2.饿汉式(线程安全):

  • 这种方式在程序启动时就创建实例,它是线程安全的,但可能会增加程序启动时间。
class Singleton {
private:
    Singleton() {} // 构造函数
    Singleton(const Singleton&) = delete; // 禁止拷贝
    Singleton& operator=(const Singleton&) = delete; // 禁止赋值

public:
    static Singleton& getInstance() {
        static Singleton instance; // 局部静态变量
        return instance;
    }
};

2.3.双重检查锁定(线程安全):

  • 这种方式在第一次使用时才创建实例,并且是线程安全的。
#include <mutex>

class Singleton {
private:
    Singleton() {} // 构造函数
    Singleton(const Singleton&) = delete; // 禁止拷贝
    Singleton& operator=(const Singleton&) = delete; // 禁止赋值

    static Singleton* instance;
    static std::mutex mutex;

public:
    static Singleton* getInstance() {
        if (instance == nullptr) {
            std::lock_guard<std::mutex> lock(mutex);
            if (instance == nullptr) {
                instance = new Singleton();
            }
        }
        return instance;
    }
};

// 初始化静态成员变量
Singleton* Singleton::instance = nullptr;
std::mutex Singleton::mutex;

2.4.单例模式的变体:使用 std::call_once(C++11):

  • 这种方式使用 std::call_once 确保线程安全,并且延迟实例的创建。
#include <mutex>

class Singleton {
private:
    Singleton() {} // 构造函数
    Singleton(const Singleton&) = delete; // 禁止拷贝
    Singleton& operator=(const Singleton&) = delete; // 禁止赋值

    static Singleton* instance;
    static std::once_flag once;

public:
    static Singleton* getInstance() {
        std::call_once(once, []() {
            instance = new Singleton();
        });
        return instance;
    }
};

// 初始化静态成员变量
Singleton* Singleton::instance = nullptr;
std::once_flag Singleton::once;

总结

Lambda 函数和单例模式都是现代 C++ 编程中的重要概念。Lambda 函数提供了一种灵活的方式来编写简短的匿名函数,而单例模式则是一种确保类只有一个实例的设计模式。在多线程环境中实现单例模式时,需要特别注意线程安全。C++11 提供了 std::call_oncestd::once_flag 这样的工具来帮助我们以线程安全的方式实现单例模式,而 Lambda 函数则因其简洁和表达力而成为编写算法和处理数据集时的首选。通过合理运用这些特性,我们可以编写出既高效又安全的代码。

代码随想录算法训练营是一个优质的学习和讨论平台,提供了丰富的算法训练内容和讨论交流机会。在训练营中,学员们可以通过观看视频讲解来学习算法知识,并根据讲解内容进行刷题练习。此外,训练营还提供了刷题建议,例如先看视频、了解自己所使用的编程语言、使用日志等方法来提高刷题效果和语言掌握程度。 训练营中的讨论内容非常丰富,涵盖了各种算法知识点和解题方法。例如,在第14训练营中,讲解了二叉树的理论基础、递归遍历、迭代遍历和统一遍历的内容。此外,在讨论中还分享了相关的博客文章和配图,帮助学员更好地理解和掌握二叉树的遍历方法。 训练营还提供了每日的讨论知识点,例如在第15的讨论中,介绍了层序遍历的方法和使用队列来模拟一层一层遍历的效果。在第16的讨论中,重点讨论了如何进行调试(debug)的方法,认为掌握调试技巧可以帮助学员更好地解决问题和写出正确的算法代码。 总之,代码随想录算法训练营是一个提供优质学习和讨论环境的平台,可以帮助学员系统地学习算法知识,并提供了丰富的讨论内容和刷题建议来提高算法编程能力。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* *3* [代码随想录算法训练营每日精华](https://blog.csdn.net/weixin_38556197/article/details/128462133)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 100%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值