C++常用容器、函数、类集(3)

发布于:2025-07-12 ⋅ 阅读:(32) ⋅ 点赞:(0)

接前一篇文章:C++常用容器、函数、类集(2)

 

7. std::lock_guard

std::lock_guard是C++11标准库(STL)中的一个类模板,用于自动管理互斥锁(std::mutex或其派生类)的锁定和解锁。其主要目的是提供一种简便且安全的方式来保护临界区(critical sections)免受数据竞争(data race)的影响。

std::lock_guard是C++11引入的互斥锁管理工具,采用RAII(资源获取即初始化)机制,自动管理锁的加锁与解锁操作,适用于多线程环境下保护临界区资源。

核心特性

  • 自动锁定与解锁‌:构造时自动加锁,析构时自动解锁,确保异常安全。
  • 异常安全‌:即使临界区代码抛出异常,锁仍会在作用域结束时释放。
  • 不可复制‌:避免多线程同时锁定同一资源,防止死锁。

代码示例:

#include <iostream>
#include <mutex>
#include <thread>
#include <vector>

std::mutex mtx;
int sharedResource = 0;

void threadFunction(int id) {
    for (int i = 0; i < 10000; ++i) {
        std::lock_guard<std::mutex> lock(mtx); // 自动加锁
        sharedResource += id;
        // 当 lock 的作用域结束时,自动解锁
    }
}

int main() {
    std::vector<std::thread> threads;

    for (int i = 0; i < 10; ++i) {
        threads.emplace_back(threadFunction, i);
    }

    for (auto& thread : threads) {
        thread.join();
    }

    std::cout << "sharedResource: " << sharedResource << std::endl;

    return 0;
}

 

8. auto

auto是C++11引入的关键字,用于自动推导变量类型,其核心作用是减少类型声明的冗余,让编译器根据初始化表达式自动确定变量类型。

基本用法

auto声明变量的类型会根据初始化表达式的类型自动推导,例如:

auto x = 42;(推导为 int) ‌14
auto y = 3.14;(推导为 double) ‌14
auto z = "Hello";(推导为 const char*)​​​​​​​

使用场景

  • 简化复杂类型声明

在模板或容器操作中避免冗长类型名。例如:

std::vector<std::unordered_map<std::string, int>> data;  
auto it = data.begin(); // 无需写成 std::vector<...>::iterator
  • 范围for循环

遍历容器时简化迭代代码。例如:

std::vector<int> vec = {1,2,3};  
for(auto& num : vec) { num *= 2; } // 使用引用避免拷贝
  • 函数返回类型推导‌(C++14 起)

允许函数返回值使用auto。例如:

auto add(int a, int b) { return a + b; } // 返回类型推导为 int

注意事项

  • 初始化要求

使用auto的变量必须初始化,否则编译错误。例如:

auto z; // 无法推导,无法通过编译
  • 作用范围

仅限局部变量,不能用于全局变量或函数参数。

 

9. std::make_shared

std::make_shared是C++11标准引入的一个函数模板,用于创建std::shared_ptr对象,并高效地分配和管理对象的内存。它比直接使用std::shared_ptr构造函数std::shared_ptr<T>(new T(...))具有更好的性能和异常安全性。

std::make_shared的优势

与std::shared_ptr<T>(new T(...))相比,std::make_shared主要有以下优点:

  • 更少的内存分配

  • 异常安全

  • 代码更简洁

代码示例:

  • 基本用法
#include <iostream>
#include <memory>

struct Foo {
    int x;
    Foo(int a) : x(a) { std::cout << "Foo constructor\n"; }
    ~Foo() { std::cout << "Foo destructor\n"; }
};

int main() {
    std::shared_ptr<Foo> sp = std::make_shared<Foo>(42);
    std::cout << "Foo.x = " << sp->x << std::endl;
    return 0;
}
  • 创建数组(C++20 及更高版本支持)
#include <iostream>
#include <memory>

int main() {
    std::shared_ptr<int[]> arr = std::make_shared<int[]>(5);
    for (int i = 0; i < 5; ++i)
        arr[i] = i * 2;
    
    for (int i = 0; i < 5; ++i)
        std::cout << arr[i] << " ";
    
    return 0;
}

 

10. std::shared_ptr

std::shared_ptr是C++11标准库(STL)中的智能指针类型,用于管理动态分配的对象。与传统指针不同,std::shared_ptr自动管理内存,并在不再使用时自动释放对象,以避免内存泄漏。它是一种共享所有权的智能指针,即可以让多个std::shared_ptr指向同一个对象,并且会记录有多少个std::shared_ptr指向该对象。

代码示例:

#include <memory>
#include <iostream>
 
struct Foo {
    Foo() { std::cout << "Foo...\n"; }
    ~Foo() { std::cout << "~Foo...\n"; }
};
 
struct D { 
    void operator()(Foo* p) const {
        std::cout << "Call delete from function object...\n";
        delete p;
    }
};
 
int main()
{
    {
        std::cout << "constructor with no managed object\n";
        std::shared_ptr<Foo> sh1;
        bool ok = sh1.get()==nullptr;
        std::cout<<ok<<'\n';
    }
    // copy构造函数的话,引用计数都会增加
    {
        std::cout << "constructor with object\n";
        std::shared_ptr<Foo> sh2(new Foo);
        std::shared_ptr<Foo> sh3(sh2);
        std::cout << sh2.use_count() << '\n'; 
        std::cout << sh3.use_count() << '\n';
    }
   // 可以指定删除的函数,并传递给构造函数
    {
        std::cout << "constructor with object and deleter\n";
        std::shared_ptr<Foo> sh4(new Foo, D());
        std::shared_ptr<Foo> sh5(new Foo, [](auto p) {
           std::cout << "Call delete from lambda...\n";
           delete p;
        });
    }
}
输出:
constructor with no managed object
1 // shared_ptr 默认构造函数分配的是空指针
constructor with object
Foo...
2 // sh2 和sh3指向的都是同一个内存,所以他们的引用计数都是2
2
~Foo...
constructor with object and deleter
Foo...
Foo...
Call delete from lambda...
~Foo...
Call delete from function object...
~Foo..

 

更多内容请看下回。

 


网站公告

今日签到

点亮在社区的每一天
去签到