施磊老师高级c++笔记(三)

绑定器和函数对象

1.bind1st 和 bind2nd

  1. 这是STL中 绑定器
    分别用于绑定二元函数的第一个或第二个参数

  2. c++11 中的 bind绑定器和 function函数对象机制

  3. lambda表达式—底层依赖函数对象的机制实现

  4. 代码:

    #include <iostream>
    #include <vector>
    #include <functional>
    #include <algorithm>
    using namespace std;
    
    template<typename Container>
    void showContainer(Container& con)
    {
        typename Container::iterator it = con.begin();  //需要加 typename,编译时并不知道什么类型
        for (; it != con.end(); ++it)
        {
            cout << *it << " ";
        }
        cout << endl;
    }
    
    int main()
    {
        vector<int> vec;
        srand(time(nullptr));   // 随机种子
        for (int i = 0; i < 20; ++i)
        {
            vec.push_back(rand() % 100 + 1);
        }
    
        showContainer(vec);
        sort(vec.begin(), vec.end());
        showContainer(vec);
    
        // greater 二元函数对象
        sort(vec.begin(), vec.end(), greater<int>()); 
        showContainer(vec);
    
        //把70按顺序 插入到vec中   使用bind1st   70>b
        auto it1 = find_if(vec.begin(), vec.end(), bind1st(greater<int>(), 70));
        if (it1 != vec.end())
        {
            vec.insert(it1, 70);
        }
        showContainer(vec);
    }
    

2.bind1st的底层实现原理

代码:

#include <iostream>
#include <vector>
#include <functional> // 用于 std::greater, std::less 等

// 自定义的 mybindist 类,模拟 bind1st 的功能
template<typename Compare, typename T>
class _mybindist
{
public:
    // 构造函数,接受一个比较函数对象和一个值
    _mybindist(Compare comp, T val)
        : _comp(comp), _val(val)
    {}

    // 重载函数调用运算符,使其成为一个函数对象
    bool operator()(const T& x) const
    {
        // 使用绑定的值和传入的参数进行比较
        return _comp(x,_val);   // 这里要根据使用 greater和less 来调整顺序
    }

private:
    Compare _comp; // 比较函数对象
    T _val;        // 绑定的值
};

// 辅助函数,用于创建 mybindist 对象
template<typename Compare, typename T>
_mybindist<Compare, T> mybindist(Compare comp, const T& val)
{
    // 返回 mybindist 对象
    return _mybindist<Compare, T>(comp, val);
}

// 自定义的 my_find_if 函数,模拟 std::find_if 的功能
template<typename Iterator, typename Predicate>
Iterator my_find_if(Iterator first, Iterator last, Predicate pred)
{
    for (; first != last; ++first)
    {
        if (pred(*first)) // 如果满足条件
        {
            return first; // 返回当前迭代器
        }
    }
    return last; // 如果没有找到,返回 last
}

int main()
{
    // 创建一个整数向量
    std::vector<int> vec = { 10, 20, 30, 40, 50, 60, 70, 80, 90, 100 };

    // 使用 mybindist 创建一个函数对象,检查元素是否大于 70
    auto greater_than_70 = mybindist(std::greater<int>(), 70);

    // 使用 my_find_if 查找第一个大于 70 的元素
    auto it = my_find_if(vec.begin(), vec.end(), greater_than_70);

    // 输出结果
    if (it != vec.end())
    {
        std::cout << "First element greater than 70 is: " << *it << std::endl;
    }
    else
    {
        std::cout << "No element greater than 70 found." << std::endl;
    }

    return 0;
}

直接使用函数模板, 好处是 可以进行 类型的 推演

处理能力有限, 只能处理二元函数对象, 多了就不行了

3.函数对象类型function–应用实例

  1. c++11的绑定器bind 与 STL中的bind1st 和 bind2nd不同, 能用, 但已被弃用

  2. STL中的bind1st 和 bind2nd ---- 本质还是函数对象

  3. 绑定器, 函数对象, lambda 表达式, 只能使用在一条语句中, 使用了function, 可以解决这个问题

  4. 补充知识点: 函数类型 和 函数指针类型 区分

    函数类型

    函数类型指的是函数的签名(signature),包括函数的返回类型和参数类型。函数类型本身并不是一个可以直接使用的对象,而是描述函数的特征。

    int add(int a, int b); // 函数类型是 int(int, int)
    void print(const std::string& str); // 函数类型是 void(const std::string&)
    

    函数类型通常用于模板参数或类型推导中。

    std::function<int(int, int)> func = add; // std::function 使用函数类型 int(int, int)
    

    函数指针类型

    函数指针类型是指向函数的指针类型。它是一个具体的对象,可以存储函数的地址,并通过指针调用函数。

    int (*funcPtr)(int, int); // 函数指针类型是 int(*)(int, int)
    funcPtr = add; // 将函数 add 的地址赋值给 funcPtr
    int result = funcPtr(2, 3); // 通过函数指针调用函数
    

    函数指针类型的语法包括:

    • 返回类型
    • 指针名称(用 * 表示)
    • 参数类型列表
  5. function 应用实例代码:
    用函数类型 实例化 function
    通过function调用operator()函数的时候, 需要根据函数类型 传入 相应的参数
    可以保留 lambda 表达式, 到处都可以使用
    最大的作用: 保留可以看到的函数, 成员方法, lambda表达式, 其他函数对象

    #include <iostream>
    #include <vector>
    #include <functional> // 用于 std::greater, std::less 等
    using namespace std;
    
    void hello1()
    {
        cout << "hello world!" << endl;
    }
    
    void hello2(string str)  // void(*pfunc)(string)
    {
        cout << str << endl;   
    }
    
    int sum(int a, int b)
    {
        return a + b;
    }
    
    class Test
    {
        // 成员方法和普通函数不同, 调用必须 依赖对象,通过函数指针调用 void(Test::*pfunc)(string)
    public:
        void hello(string str) { cout << str << endl; }
    };
    
    int main()
    {
        // 从function的类模板定义处,看到希望用一个函数类型实例化function 
        
        function<void()> func1 = hello1;  
        func1();  // func1.operator()=>hello1()
    
        function<void(string)> func2 = hello2;  // 
        func2("hello2");  // func2.operator()(string str)=>hello2(string)
    
        function<int(int, int)> func3 = sum;
        cout << func3(4, 5) << endl;
    
        // function + lambda
        function<int(int, int)> func4 = [](int a, int b)->int {return a + b; };
        cout << func4(40, 50) << endl;
    
        // function+成员方法
        // 课里讲的 这个在高版本 编译不了, & 必须跟左值
        //function<void(Test*, string)> func5 = &Test::hello;
        //func5(&Test(), "call Tes::hello!");  // &Test() 临时对象地址
    
        function<void(Test&&, string)> func5 = &Test::hello;
        func5(Test(), "call Tes::hello!");  // &Test() 临时对象地址
    
        return 0;
    }
    
    
  6. 特别注意: 成员方法第一个参数, 都是 this指针!!!, 不要忽略, 这不像python, python会标出self, cpp不会标this指针

  7. 实际的 应用案例之一:
    这样的代码 无法闭合, 无法做到 “开-闭原则”, 无法通过添加代码完成修改, 而是需要 修改原本的代码

#include <iostream>
using namespace std;

int main() {
    int choice;
    cout << "1.查看所有书籍信息" << endl;
    cout << "2.借书" << endl;
    cout << "3.还书" << endl;
    cout << "4.查询书籍" << endl;
    cout << "5.注销" << endl;
    cout << "---" << endl;
    cout << "请选择:";
    cin >> choice;

    switch (choice) {
        case 1:
            // 查看所有书籍信息的代码
            cout << "查看所有书籍信息" << endl;
            break;
        case 2:
            // 借书的代码
            cout << "借书" << endl;
            break;
        case 3:
            // 还书的代码
            cout << "还书" << endl;
            break;
        case 4:
            // 查询书籍的代码
            cout << "查询书籍" << endl;
            break;
        case 5:
            // 注销的代码
            cout << "注销" << endl;
            break;
        default:
            cout << "无效的选择,请重新选择。" << endl;
            break;
    }

    return 0;
}

优化:----function应用

#include <iostream>
#include <functional>
#include <map>
using namespace std;

void doshowbooks(){ cout << "查看所有书籍信息" << endl; }
void doborrow(){ cout <<"借书" << endl; }  // ...

int main() {
    int choice;

    map<int, function<void()>> actionmap;
    actionmap.insert({ 1,doshowbooks });  // 低版本使用 .insert(make_pair(1,do))
    actionmap.insert({ 2,doborrow});

    cout << "1.查看所有书籍信息" << endl;
    cout << "2.借书" << endl;
    cout << "---" << endl;
    cout << "请选择:";
    cin >> choice;
    auto it = actionmap.find(choice);
    if (it == actionmap.end())
    {
        cout << "no message!" << endl;
    }
    else
    {
        it->second();  //注意()
    }
    return 0;
}

4.模板的完全特例化和部分特例化

有完全特例化 版本, 优先匹配 完全特例化版本

回顾完全特例化

#include <iostream>
#include <cstring> // 用于 strcmp 函数
using namespace std;


// 通用模板函数
template<typename T>
bool compare(T a, T b)
{
    return a > b;
}

// 特化版本,用于 const char* 类型
template<>
bool compare<const char*>(const char* a, const char* b)
{
    return strcmp(a, b) > 0;
}

int main()
{
    // 使用通用模板比较整数
    compare(10, 20);

    // 使用特化版本比较 C 风格字符串
    compare("aaa", "bbb");

    return 0;
}

部分特例化

#include <iostream>
using namespace std;

// 通用模板类
template<typename T>
class Vector
{
public:
    Vector() { cout << "call Vector template init" << endl; }
};

// 完全特例化版本,针对 char* 类型
template<>
class Vector<char*>
{
public:
    Vector() { cout << "call Vector<char*> init" << endl; }
};

// 部分特例化版本,针对所有指针类型
template<typename Ty>
class Vector<Ty*>
{
public:
    Vector() { cout << "call Vector<Ty*> init" << endl; }
};

// 部分特例化版本,针对两个参数的函数指针类型
template<typename R, typename A1, typename A2>
class Vector<R(*)(A1, A2)>
{
public:
    Vector() { cout << "call Vector<R(*)(A1, A2)> init" << endl; }
};

int sum(int a, int b)
{
    return a + b;
}

int main()
{
    // 使用通用模板类
    Vector<int> intVector; // 调用通用模板构造函数

    // 使用完全特例化版本
    Vector<char*> charPtrVector; // 调用 char* 特例化构造函数

    // 使用部分特例化版本
    Vector<int*> intPtrVector; // 调用指针类型的部分特例化构造函数

    //函数指针, 也是指针
    Vector<int(*)(int, int)> funcPtrVector; // 没有函数指针特例化, 就用匹配的部分特例化
    //这是函数类型, 不是函数指针
    Vector<int(int, int)> funcVector;

    typedef int(*PFUNCPTR)(int, int);
    PFUNCPTR func1 = sum;
    cout << func1(10, 20) << endl;

    return 0;
}

注意区分函数类型和函数指针类型

模板的实参推演

实例–细分:

#include <iostream>
#include <typeinfo> // 用于 typeid 和 type_info
using namespace std;

// 模板函数,用于打印类型信息
template<typename T>
void func(T a)
{
    cout << "Type of T: " << typeid(T).name() << endl;
}
// 模板函数,用于打印类型信息
template<typename T>
void func2(T* a)
{
    cout << "Type of T: " << typeid(T).name() << endl;
}

template<typename R, typename A1, typename A2>
void func3(R(*a)(A1, A2))
{ 
        cout << "Type of T: " << typeid(R).name() << endl;
        cout << "Type of A1: " << typeid(A1).name() << endl;
        cout << "Type of A2: " << typeid(A2).name() << endl;
    }

class Test
{
public:
    int sum(int a, int b) { return a + b; }
};

template<typename R, typename A1, typename A2, typename T>
void func4(R(T::*a)(A1, A2))  // a这种, 存不存在都行, 因为没使用
{
    cout << "Type of R: " << typeid(R).name() << endl;
    cout << "Type of T: " << typeid(T).name() << endl;
    cout << "Type of A1: " << typeid(A1).name() << endl;
    cout << "Type of A2: " << typeid(A2).name() << endl;
}

// 普通函数,计算两个整数的和
int sum(int a, int b) {
    return a + b;
}

int main()
{
    // 调用 func 并传入整数
    func(10); // T 推导为 int

    // 调用 func 并传入字符串字面量
    func("aaa"); // T 推导为 const char*

    // 调用 func 并传入函数指针
    func(sum); // T 推导为 int (*)(int, int)
    func2(sum);  // int __cdecl(int,int)

    //细分类型
    func3(sum);

    func(&Test::sum); //  int (__thiscall Test::*)(int,int)
    func4(&Test::sum);

    return 0;
}

5.function实现原理

固定参模板

一般的 自己写的 function 会因为形参个数不同, 导致需要特例化 太多, 如下:

#include <iostream>
#include <string>
using namespace std;

// 模板类,封装函数指针
template<typename R, typename A1>
class myfunction {
public:
    using PFUNC = R(*)(A1); // 定义函数指针类型

    // 构造函数,接受一个函数指针
    myfunction(PFUNC pfunc) : _pfunc(pfunc) {}

    // 重载 operator(),使对象可以像函数一样调用
    R operator()(A1 arg) {
        return _pfunc(arg);
    }

private:
    PFUNC _pfunc; // 存储函数指针
};

// 示例函数,用于测试
void hello(string str) {
    cout << "Hello, " << str << endl;
}

int main() {
    // 创建 myfunction 对象,封装 hello 函数
    myfunction<void, string> func1(hello);

    // 调用 func1,输出 "Hello, hello world!"
    func1("hello world!");

    return 0;
}

但是,c++11提供了 可变参的模板

可变参模板–>…

typename… A

template<typename R, typename... A>
class myfunction {
public:
    using PFUNC = R(*)(A...); // 定义函数指针类型

    // 构造函数,接受一个函数指针
    myfunction(PFUNC pfunc) : _pfunc(pfunc) {}

    // 重载 operator(),使对象可以像函数一样调用
    R operator()(A... arg) {
        return _pfunc(arg);
    }

private:
    PFUNC _pfunc; // 存储函数指针
};

6.c++11的bind–头文件 functional

返回的结果 还是 一个函数对象

bind 是 函数模板 – 也就能 自动推演类型了

不要忘记 bind(…)()最后这个括号

1.无参数占位符

#include <iostream>
#include <string>
#include <functional>
using namespace std;


// 示例函数,用于测试
void hello(string str) {
    cout << "Hello, " << str << endl;
}
int sum(int a, int b) {
    return a + b;
}

class Test
{
    // 成员方法和普通函数不同, 调用必须 依赖对象,通过函数指针调用 void(Test::*pfunc)(string)
public:
    int sum(int a, int b) {
        return a + b;
    }
};

int main() {

    bind(hello, "hello bind!")(); 
    cout<<bind(sum, 10, 20)()<<endl;

    cout << bind(&Test::sum, Test(), 20, 30)() << endl; // 注意绑定Test对象

    return 0;
}

2.有参数占位符–placeholders::_

 //参数占位符
    bind(hello, placeholders::_1)("hello placeholders");

//placeholders 是一个命名空间
using namespace placeholders;
bind(hello, _1)("hello placeholders");

3.绑定器+function

绑定器 出了 语句无法继续使用

function<void(string)> func1 = bind(hello, placeholders::_1);
func1("hello shanxi");
func1("hello shanxi-2");

bind原本是 boost库里的, c++11 放到了 标准库

4.使用bind+function 实现 简单的 线程池

只学过c的线程池, 可能看不明白, 后续会写 c++的多线程 笔记

#include <iostream>
#include <vector>
#include <thread>
#include <functional> // 包含 std::bind
#include <memory>     // 包含 std::unique_ptr
using namespace std;

class Thread {
public:
    Thread(function<void()> func) : _func(func) {}  // function用于接收 bind

    thread start() {
        return thread(_func);
    }

private:
    function<void()> _func;
};

class ThreadPool {
public:
    // 开启线程池
    void startPool(int size) {
        for (int i = 0; i < size; ++i) {
            _pool.push_back(new Thread(bind(&ThreadPool::runInThread, this, i))); //不使用占位符, 将不用再次传参
        }

        for (int i = 0; i < size; ++i) {
            _handler.push_back(_pool[i]->start());
        }

        for (thread& t : _handler) {
            if (t.joinable()) {
                t.join();
            }
        }
    }

    // 清理线程池
    ~ThreadPool() {
        for (int i = 0; i < _pool.size(); ++i) {
            delete _pool[i];
        }
        
    }

private:
    vector<Thread*> _pool; // 使用智能指针管理线程对象
    vector<thread> _handler;          // 存储线程对象

    // 线程函数
    void runInThread(int id) {
        cout << "Thread " << id << " is running!" << endl;
    }
};

int main() {
    ThreadPool pool;
    pool.startPool(10); // 开启一个包含 10 个线程的线程池

    return 0;
}

可以使用智能指针, 自动释放
make_unique 是c++14加入的工具函数
在容器中存储 unique_ptr 时,推荐使用 make_unique
容器中 不能使用 new 传给 智能指针

#include <iostream>
#include <vector>
#include <thread>
#include <functional> // 包含 std::bind
#include <memory>     // 包含 std::unique_ptr
using namespace std;

class Thread {
public:
    Thread(function<void()> func) : _func(func) {}  // function用于接收 bind

    thread start() {
        return thread(_func);
    }

private:
    function<void()> _func;
};

class ThreadPool {
public:
    // 开启线程池
    void startPool(int size) {
        for (int i = 0; i < size; ++i) {
            _pool.push_back(make_unique<Thread>(bind(&ThreadPool::runInThread, this, i))); //不使用占位符, 将不用再次传参
        }

        for (int i = 0; i < size; ++i) {
            _handler.push_back(_pool[i]->start());
        }

        for (thread& t : _handler) {
            if (t.joinable()) {
                t.join();
            }
        }
    }

    // 清理线程池
    ~ThreadPool() {

    }

private:
    vector<unique_ptr<Thread>> _pool; // 使用智能指针管理线程对象
    vector<thread> _handler;          // 存储线程对象

    // 线程函数
    void runInThread(int id) {
        cout << "Thread " << id << " is running!" << endl;
    }
};

int main() {
    ThreadPool pool;
    pool.startPool(10); // 开启一个包含 10 个线程的线程池

    return 0;
}

7.lambda表达式

  1. 函数对象相较于 lambda 的缺点

    1. 代码冗长:需要定义类,lambda 只需一行代码。
    2. 不能直接捕获外部变量:必须手动存储,而 lambda 可自动捕获。
    3. 不适用于局部作用域lambda 可随用随写,函数对象需额外定义类。
    4. 使用标准算法较繁琐lambda 直接传入算法,函数对象需单独定义。
    5. 不能自动推导类型:函数对象 operator() 需显式指定返回类型,lambda 可自动推导。
  2. lambda表达式语法:
    [捕获外部变量](形参列表)->返回值 {操作代码}
    如果返回值不需要, 可以省略->返回值
    [] : 表示 不捕获外部变量
    [=] : 以传值的方式 捕获的所有变量
    [&] : 以引用的方式 捕获的所有变量
    [this] : 捕获外部 this指针
    [=, &a] : 以传值的方式 捕获的所有变量, 但是a是引用方式捕获
    [a, b] : 以传值的方式 捕获 外部 a,b
    [a,&b] : 以传值的方式 捕获 a, 但是b是引用方式捕获

  3. mutable 关键字
    在 C++ 中,mutable 是一个关键字,用于修饰类的成员变量。它的主要作用是允许在 const 成员函数中修改被 mutable 修饰的成员变量。mutable 通常用于那些逻辑上不改变对象状态,但技术上需要修改某些成员变量的场景。

    class Counter {
    public:
        Counter() : _count(0) {}
    
        void increment() const {
            ++_count; // 允许在 const 成员函数中修改 _count
        }
    
        int getCount() const {
            return _count;
        }
    
    private:
        mutable int _count; // 使用 mutable 修饰
    };
    
    int main() {
        const Counter counter;
        counter.increment(); // 调用 const 成员函数
        std::cout << "Count: " << counter.getCount() << std::endl; // 输出: Count: 1
        return 0;
    }
    
  4. lambda代码示例: — 使用auto

    可以回顾一下 STL中使用lambda的点
    注意 成员变量是左值引用时, 不在定义出初始化, 而是在构造函数里

    #include <iostream>
    using namespace std;
    
    template<typename T=void>   // 注意这个 void   lambda的原理
    class TestLambda01 {
    public:
        void operator()() {
            cout << "hello world!" << endl;
        }
    };
    template<typename T = int>   // 注意这个 void   lambda的原理
    class TestLambda02 {
    public:
        TestLambda02(int a, int b):ma(a),mb(b){}
        void operator()() const{
            int tmp = mb;
            mb = ma;
            ma = tmp;
        }
    private:
        int ma;
        int mb;
    };
    
    template<typename T = int>   // 注意这个 void   lambda的原理
    class TestLambda03 {
    public:
        TestLambda03(int &a, int &b) :ma(a), mb(b) {}
        void operator()() const {
            int tmp = mb;
            mb = ma;
            ma = tmp;
        }
    private:
        int &ma;  // C++ 规定引用成员变量必须在构造函数的初始化列表中初始化。  所以这里不需要初始化
        int &mb;
    };
    
    int main() {
        auto func1 = []()->void { cout << "hello world!" << endl; };
        func1();
    
        auto func2 = []() { cout << "hello world!" << endl; };
        func2();
    
        int a = 10;
        int b = 20;
        //auto func3 = [=]() {  // 类似于 TestLambda02
        //    int tmp = b;
        //    b = a;   // lambda 默认是 是使用常方法, 因此不能修改值
        //    a = tmp;
        //    cout << "hello world!" << endl; };
        auto func3 = [=]()mutable {   // mutable 表示 可以在常方法中修改成员变量
            int tmp = b;
            b = a;  
            a = tmp;
            cout << "hello world!" << endl; };
        func3();
        cout << "a " << a << endl;   // 因为是值传递, 外边的没改变
    
    
    
        TestLambda01<> t1; //这种太冗余了
        t1();
       /* TestLambda02<int> t2(20, 30);
        t2();*/
        TestLambda03<int> t3(a, b);
        t3();
    
        return 0;
    }
    
    

8.lambda表达式应用实践–跨语句–function

需要多多练习 代码使用方式

#include <iostream>
#include <memory>
#include <map>
#include <functional>
#include <queue>
using namespace std;

class Data {
public:
    Data(int val1 = 10, int val2 = 10) : ma(val1), mb(val2) {}
    int ma;
    int mb;
};

// 自定义删除器   这个就有点繁琐了 可以使用function+lambda
void fileDeleter(FILE* file) {
    if (file) {
        fclose(file);
        cout << "File closed." << endl;
    }
}

int main() {
    // 使用自定义删除器的 unique_ptr
    unique_ptr<FILE, decltype(&fileDeleter)> ptr1(fopen("test.txt", "w"), fileDeleter);
    if (ptr1) {
        fprintf(ptr1.get(), "Hello, World!\n");
    }

    // 函数映射
    map<int, function<int(int, int)>> calculateMap;
    calculateMap[1] = [](int a, int b) -> int { return a + b; };
    calculateMap[2] = [](int a, int b) -> int { return a - b; };
    calculateMap[3] = [](int a, int b) -> int { return a * b; };
    calculateMap[4] = [](int a, int b) -> int { return a / b; };

    cout << "选择操作 (1: 加, 2: 减, 3: 乘, 4: 除): ";
    int choice;
    cin >> choice;

    if (calculateMap.find(choice) != calculateMap.end()) {
        int a, b;
        cout << "输入两个整数: ";
        cin >> a >> b;
        cout << "结果: " << calculateMap[choice](a, b) << endl;
    }
    else {
        cout << "无效的选择。" << endl;
    }

    
    // 使用自定义比较函数的优先级队列, 这样更 灵活, 如果写函数, 会很死板 
    using FUNC = function<bool(Data&, Data&)>;
    priority_queue<Data, vector<Data>, FUNC> maxHeap(
        [](Data& d1, Data& d2) -> bool {
            return d1.ma > d2.ma; // 大顶堆,按 ma 从大到小排序
        }
    );

    // 添加元素
    maxHeap.push(Data(5, 20));
    maxHeap.push(Data(15, 10));
    maxHeap.push(Data(10, 30));

    // 输出元素
    while (!maxHeap.empty()) {
        Data top = maxHeap.top();
        cout << "ma: " << top.ma << ", mb: " << top.mb << endl;
        maxHeap.pop();
    }

    return 0;
}
### 施磊 C++ muduo 项目介绍 muduo是一个高性能的C++网络库,由陈硕开发并维护。此库广泛应用于高并发服务器程序的设计与实现中[^2]。 #### 主要特性 - **线程安全**:通过`shared_ptr`和`weak_ptr`解决多线程环境下共享资源的安全访问问题。 - **高效性能**:针对Linux平台进行了大量优化,能够处理大量的并发连接请求。 - **易于扩展**:提供了丰富的接口供开发者自定义协议解析逻辑和服务端业务流程控制。 #### 使用场景 适用于构建各种类型的分布式系统,特别是需要频繁通信的服务间交互模块。例如即时通讯软件、在线游戏后台等都需要依赖类似的框架来保证系统的稳定性和响应速度。 ```cpp // 创建TCP服务器实例 TcpServer server(loop, InetAddress(listenPort), "EchoServer"); server.setConnectionCallback( std::bind(&onConnection, _1)); server.setMessageCallback( std::bind(&onMessage, _1, _2, _3)); server.start(); loop.loop(); ``` 上述代码展示了如何利用muduo创建一个简单的回声(Echo) TCP Server,在这里注册了两个回调函数分别用于新连接建立以及接收到消息后的事件触发。 #### 学习路径建议 对于想要深入了解该项目的同学来说,可以从以下几个方面入手: - 阅读官方文档及注释说明; - 参考施磊老师的《C++课程笔记》系列资料中的相关内容部分[^1]; - 实践操作启动样例工程,熟悉基本命令行指令[^3];
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值