C++核心编程解析:模板、容器与异常处理全指南

news2025/5/13 9:02:00

文章目录

  • 一、模板
    • 1.1 定义
    • 1.2 作用
    • 1.3 函数模版
      • 1.3.1 格式
    • 1.4 类模版
      • 1.4.1 格式
      • 1.4.2 代码示例
      • 1.4.3 特性
  • 二、容器
    • 2.1 概念
    • 2.2 容器特性
    • 2.3 分类
    • 2.4 向量vector
      • 2.4.1 特性
      • 2.4.2 初始化与操作
      • 2.4.3 插入删除
    • 2.5 迭代器
    • 2.6 列表(list)
      • 2.6.1 遍历方式
      • 2.6.2 插入与删除操作
    • 2.7队列(Deque)
      • 2.7.1定义与基本特性
      • 2.7.2 内部实现机制
    • 2.8. map 容器
      • 2.8.1 特性
      • 2.8.2 定义格式
      • 2.8.3 遍历方式
      • 2.8.4 插入删除查找操作
  • 三、C++异常处理详解
    • 3.1 异常基本概念
    • 3.2 异常处理机制
    • 3.3 简易异常实现
    • 3.4 标准异常
    • 3.5 自定义异常
  • 四、文件流
  • 总结


一、模板

1.1 定义

C++模板是支持参数化多态的工具,允许类或函数声明为通用类型,使得其数据成员、参数或返回值在实际使用时可以是任意类型。模板通过编译器生成具体代码,实现类型无关的逻辑复用。


1.2 作用

实现泛型编程,提高代码的通用性和复用性。
避免为不同数据类型重复编写相同逻辑的代码。


1.3 函数模版

1.3.1 格式

template <typename T1, typename T2, ...> 
返回类型 函数名(参数列表) {
    // 函数体
}
  • 关键字 typename 或 class 均可用于声明类型参数,typename 更推荐(尤其在处理依赖类型时)。

代码示例

#include<iostream>
using namespace std;

// 通用加法函数模板
// T: 第一个参数和返回值的类型
// C: 第二个参数的类型
// 当T和C类型不同时,返回值类型与第一个参数类型保持一致
template <class T, class C>
T add(T a, C b) {
        return a + b;
}

int main() {
        // 测试整型相加(int + int)
        cout << add(1, 2) << endl;

        // 测试浮点型相加(double + double)
        cout << add(1.1, 2.2) << endl;

        // 测试字符类型相加(char + char),ASCII码值运算
        cout << add('A',' ') << endl;

        // 测试字符串拼接(string + string)
        string s1 = "Hello";
        string s2 = "World";
        cout << add(s1, s2) << endl;

        // 测试混合类型相加(int + char),返回int类型
        cout << add(32, 'A') << endl;

        // 测试混合类型相加(double + int),返回double类型
        cout << add(32.1, 2) << endl;

        return 0;

1.4 类模版

1.4.1 格式

template <typename T1, typename T2, ...>
class 类名 {
    // 类成员
};

1.4.2 代码示例

#include<iostream>
using namespace std;

// 定义一个模板类Test,T为泛型类型参数
template <class T>
class Test{
public:
    // 构造函数,使用类型T的参数初始化成员变量num
    Test(T n):num(n){}
    
    // 声明公有成员函数getVal,返回类型为T,const表示不修改对象状态
    T getVal()const;
    
private:
    T num; // 私有成员变量,类型为T
};

// 类外定义模板成员函数getVal()
// 注意模板类成员函数在类外定义时需要再次声明模板参数
template <class T>
T Test<T>::getVal()const{
    return num; // 返回成员变量num的值
}

int main()
{
    // 实例化Test类,指定类型参数为int,并初始化值为100
    Test<int> tt(100);
    // 调用getVal()获取存储的值并输出
    cout << tt.getVal() << endl; // 输出: 100

    // 实例化Test类,指定类型参数为float,并初始化值为3.14
    Test<float> t1(3.14);
    cout << t1.getVal() <<endl; // 输出: 3.14

    return 0;
}

1.4.3 特性

  • 作用域限制:模板只能在全局、命名空间或类作用域中声明,不能在局部作用域(如函数内)定义。
  • 成员函数定义:类外定义时需重复模板声明,并使用 类名:: 限定作用域。
  • 显式实例化:使用类模板时必须指定具体类型参数。

二、容器

2.1 概念

C++标准模板库(STL)提供基于模板的通用组件,包含容器、迭代器、算法等核心部件,用于高效处理数据存储和操作任务。


2.2 容器特性

类型一致性: 容器内元素类型必须相同(与Python不同)
内存管理:
默认使用栈内存,无需手动new/delete
动态容器(如vector)自动管理堆内存
操作效率: 不同容器对插入/删除/随机访问的性能差异显著


2.3 分类

类型容器特性
顺序容器vector动态数组,连续内存,随机访问高效
list双向链表,非连续内存,插入删除高效
deque双端队列,分段连续内存,首尾操作高效
关联容器map红黑树实现,键值对有序存储,键唯一
set有序唯一键集合
unordered_map哈希表实现,无序存储,平均O(1)访问

2.4 向量vector

2.4.1 特性

底层结构: 动态数组
时间复杂度:
随机访问:O(1)
尾部操作:O(1)
中间插入/删除: O(n)
头文件: #include < vector >


2.4.2 初始化与操作

#include <vector>
using namespace std;
int main()
{
    // 定义一个空的vector对象v1,使用默认构造函数初始化
    vector <int>v1;
    
    // 定义一个有5个元素的向量v2,元素进行值初始化(int类型默认初始化为0)
    vector <int>v2(5);
    
    // 定义一个有5个元素的向量v3,每个元素的初始值均为4
    vector <int>v3(5, 4);
    
    // 使用C++11的列表初始化定义向量v4,直接包含元素{5,6,4,3,2}
    // 此语法需要编译器支持C++11及以上标准
    vector <int>v4{5,6,4,3,2};
}

在QT编译中支持C++11版本的修改方式:
在.pro中增加下面内容:

CONFIG += c++11

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

int main()
{
    // 使用C++11的列表初始化语法创建并初始化vector
    vector <int> v4{5, 6, 4, 3, 2};

    // 使用传统的for循环遍历vector
    for(int i = 0; i < v4.size(); i++){
        // 使用at()成员函数访问元素,at()会进行边界检查,更安全
        cout << v4.at(i) << endl;
    }

    // 使用下标操作符修改vector中的元素
    // 注意:下标操作符不进行边界检查,访问越界会导致未定义行为
    v4[3] = 100;

    // 使用C++11的范围for循环遍历vector
    // 这种语法更简洁,i依次获取v4中的每个元素的副本
    for(int i : v4){
        cout << i << endl;
    }

    return 0; // 表示程序正常结束
}

2.4.3 插入删除

int main()
{
    // 创建并初始化一个整型vector容器
    vector<int> v4{5, 6, 4, 3, 2};

    // 清除容器(当前被注释)
    //    v4.clear();
    
    // 判断容器是否为空(1表示空,0表示非空)(当前被注释)
    //    cout << v4.empty() << endl;

    // 在容器尾部追加元素(注意类型转换)
    v4.push_back(10);         // 直接追加整型
    v4.push_back(20.5);       // double类型会被截断为整型20
    v4.push_back('a');        // char类型会转换为ASCII码97

    // 迭代器操作(当前被注释)
    //    cout << *(v4.begin()+2) << endl;  // 访问第3个元素(下标2)
    //    cout << *(v4.end()-1) << endl;    // 访问最后一个元素

    // 在容器头部插入元素222
    v4.insert(v4.begin(), 222);
    // 在倒数第三个位置插入元素333
    v4.insert(v4.end() - 2, 333);

    // 移除容器最后一个元素(当前会移除ASCII码97对应的元素)
    v4.pop_back();
    
    // 移除容器第一个元素(当前会移除头部元素222)
    v4.erase(v4.begin());

    // 遍历输出容器当前所有元素
    // 最终元素顺序:5,6,4,3,2,10,20,333,97 -> 经过删除操作后变为:
    // 6,4,3,2,10,333,20(注意实际执行后建议调试验证)
    for(int i : v4) {
        cout << i << endl;
    }
    
    return 0;
}

2.5 迭代器

类型:
iterator:可读写
const_iterator:只读
reverse_iterator:反向遍历
失效问题: 容器结构变更(如vector扩容)可能导致迭代器失效

容器类型 <数据类型>::iterator 迭代器变量名;
容器类型 <数据类型>::const_iterator 迭代器变量名;

#include<iostream>  // 引入输入输出流库
#include <vector>   // 引入向量容器库
using namespace std; // 使用标准命名空间,避免std::前缀

int main()
{
    // 创建并初始化整型向量v4,包含元素5,6,4,3,2
    vector <int>v4{5,6,4,3,2};

    // 定义可读写的迭代器,指向向量v4的起始位置
    vector <int>::iterator it = v4.begin();
    // 若使用const_iterator则无法通过迭代器修改元素(注释掉的备用方案)
    //    vector <int>::const_iterator it = v4.begin();

    // 通过迭代器修改向量第一个元素的值
    *it = 100;

    // 使用迭代器遍历向量:从当前位置(it)开始,直到超过末尾(end)
    for(; it < v4.end();it++)
        cout << *it << endl; // 解引用迭代器,输出当前元素值

    return 0; // 程序正常退出
}

2.6 列表(list)

列表是C++标准模板库(STL)中的双向链表实现。其特点如下:

内部结构: 由双向链表实现,元素内存地址不连续,通过指针链接。
访问特性:
不支持随机访问(不能使用at()或[]操作符)。
需通过迭代器顺序访问,迭代器类型为双向迭代器(仅支持++、–操作)。
性能特点:
擅长任意位置的插入和删除操作(时间复杂度为 O(1),但需先遍历到操作位置)。
与vector功能互补: vector长于随机访问和尾部操作,list长于频繁插入删除。


2.6.1 遍历方式

#include<iostream>      // 输入输出流头文件
#include<list>          // 列表容器头文件
using namespace std;    // 标准命名空间

int main()
{
    list <int>ls{4, 3, 2, 5, 1, 6};  // 初始化双向链表容器

    // 通过双向迭代器进行遍历(不支持随机访问)
    list <int>::iterator it = ls.begin();  // 获取起始迭代器
    
    // list迭代器只能使用前/后递增运算符移动
    // 注意:迭代器自增后指向第二个元素(3)
    cout << *(++it) << endl;  // 输出:3
    
    // 从第二个元素开始遍历(当前迭代器已自增)
    for(; it != ls.end(); it++){  // 遍历直到链表末尾
        cout << *it << endl;      // 输出:3 → 2 → 5 → 1 → 6
    }
    return 0;
}

2.6.2 插入与删除操作

基础操作(与vector类似):

list<int> ls{4, 3, 2, 5, 1, 6};
// 头部操作
ls.push_front(100);  // 头部插入
ls.pop_front();      // 头部删除
// 尾部操作
ls.push_back(99);    // 尾部插入
ls.pop_back();       // 尾部删除
// 访问首尾元素
cout << "Head: " << ls.front() << endl;  // 输出头部元素
cout << "Tail: " << ls.back() << endl;   // 输出尾部元素
列表特有操作:

排序:

ls.sort();  // 默认升序排序(成员函数,时间复杂度O(n log n))

注意:需使用成员函数sort(),而非标准库的std::sort()(因后者需随机访问迭代器)。

去重:

ls.unique();  // 移除相邻重复元素(通常先排序后使用)

合并链表:

list<int> ls2{7, 8, 9};
ls.merge(ls2);  // 合并后ls2为空,ls包含合并后的有序元素(需双方已排序)

删除特定值:

ls.remove(3);  // 删除所有值为3的元素

反转链表:

ls.reverse();  // 反转链表顺序

2.7队列(Deque)

2.7.1定义与基本特性

双端队列(Double-Ended Queue,Deque)是一种允许在头部和尾部高效插入、删除元素的线性数据结构。它结合了向量(动态数组)和链表的优点,支持两端操作的时间复杂度为 ,同时提供接近向量的随机访问性能。


2.7.2 内部实现机制

分块存储结构

Deque 内部由多个固定大小的数组块组成,每个块独立分配内存。
当头部或尾部空间不足时,仅需分配新块并链接,无需整体复制(如向量扩容)。
例如:一个典型的实现可能维护一个中央索引数组,记录所有块的地址,通过计算快速定位元素。

高效的两端操作

头部插入/删除:若当前头块未满,直接操作;否则分配新块。
尾部插入/删除:类似头部逻辑,尾部块不足时扩展新块。


2.8. map 容器

2.8.1 特性

关联容器: 键值对(Key-Value)存储,类似 Python 的 dict。
底层实现: 基于红黑树(自平衡二叉搜索树),保证元素按键有序(默认升序)。
时间复杂度: 插入、删除、查找操作的平均和最坏时间复杂度均为 O(log n)。
键的特性:
唯一性: 键不可重复。
有序性: 键自动排序,需支持比较操作(默认 operator<)。
迭代器稳定性:
插入操作不会使迭代器失效(除非容器被销毁)。
删除操作仅影响被删除元素的迭代器。


2.8.2 定义格式

#include <map>
using namespace std;

// 默认定义(升序)
map<KeyType, ValueType> myMap;

// 自定义排序规则
struct Compare {
    bool operator()(const KeyType& a, const KeyType& b) const {
        return a > b;  // 降序排列示例
    }
};
map<KeyType, ValueType, Compare> customOrderMap;

2.8.3 遍历方式

#include<iostream>      // 输入输出流头文件
#include<map>           // 关联容器头文件(键值对存储)
using namespace std;    // 标准命名空间

int main()
{
    // 初始化map容器(键:string类型,值:int类型)
    map <string, int> mp = {{"num",101},{"age", 20}};

    // 通过下标运算符修改值
    mp["num"] = 200;             // 修改键"num"对应的值
    cout << mp["num"] << endl;   // 输出:200

    // 通过at方法安全访问值(会检查键是否存在)
    cout << mp.at("age") << endl; // 输出:20

    // 通过双向迭代器遍历map
    map <string, int>::iterator it = mp.begin();
    for(; it != mp.end(); it++){
        // first访问键,second访问值
        cout << it->first << ":" << it->second << endl; // 输出键值对
    }
    return 0;
}

2.8.4 插入删除查找操作

#include<iostream>      // 输入输出流头文件
#include<map>           // 关联容器头文件(键值对存储)
using namespace std;    // 标准命名空间

int main()
{
    map <string, int> mp = {{"num",101},{"age", 20}};

    // 通过pair对象插入新键值对
    mp.insert(pair<string, int>("weight", 88));  // 显式构造pair插入
    // 使用make_pair自动推导类型插入
    mp.insert(make_pair("name", 123));          // 更简洁的pair创建方式

    // 通过键值删除元素(删除"age"对应的键值对)
    mp.erase("age");                            // 返回删除元素的数量

    // 查找键"num"并输出对应值(需确保存在)
    cout << mp.find("num")->second << endl;      // 输出:101
    
    // 安全查找机制:验证find结果是否为有效迭代器
    if(mp.find("num") != mp.end()){             // 判断是否找到键
        mp["num"] = 18;                         // 安全修改值
    }
    else{
        cout << "没有找到" << endl;              // 未找到时的处理
    }
    return 0;
}

三、C++异常处理详解

3.1 异常基本概念

定义:程序运行期间发生的非正常情况(如除零错误、越界访问等)。
核心作用:通过throw抛出异常、try监控代码块、catch捕获异常,实现错误控制权的转移,避免程序崩溃。
处理必要性:未处理的异常会导致程序终止。

3.2 异常处理机制

关键字:throw、try、catch
语法结构:

try {
    // 可能抛出异常的代码(保护代码)
} catch (ExceptionType1& e1) {
    // 处理 ExceptionType1 类型异常
} catch (ExceptionType2& e2) {
    // 处理 ExceptionType2 类型异常
} catch (...) {
    // 捕获所有其他类型异常
}

3.3 简易异常实现

#include<iostream>      // 输入输出流头文件
using namespace std;    // 标准命名空间

// 带异常检查的除法函数
// 参数:a-被除数,b-除数
// 返回值:整型除法结果
int divs(int a, int b)
{
    if(b == 0){                         // 检查除数合法性
        string s("除数为0");            // 创建异常描述字符串
        throw s;                       // 抛出字符串类型异常
    }
    return a/b;                        // 执行安全除法运算
}

int main()
{
    try{                               // 异常监控代码块
        // 调用可能抛出异常的除法运算
        cout << divs(4, 0) << endl;    // 触发异常的调用点
    }
    catch(string &s){                 // 捕获字符串类型异常
        cout << s << endl;            // 输出异常描述信息
    }
    return 0;                         // 程序正常退出
}

3.4 标准异常

头文件: < stdexcept >(提供常见异常类型如invalid_argument、out_of_range等)。
特点:
标准异常类继承自std::exception,通过多态统一处理。
使用what()方法获取错误信息。
示例:

#include<iostream>      // 输入输出流头文件
using namespace std;    // 标准命名空间

// 带异常检查的除法函数
// 参数:a-被除数,b-除数
// 返回值:整型除法结果
int divs(int a, int b)
{
    if(b == 0){                         // 检查除数合法性
        // 抛出标准库异常对象(比原始字符串更规范)
        throw invalid_argument("除数为0");  // 构造带错误信息的异常对象
    }
    return a/b;                        // 执行安全除法运算
}

int main()
{
    try{                               // 异常监控代码块
        // 调用可能抛出异常的除法运算
        cout << divs(4, 0) << endl;    // 触发异常的调用点
    }
    catch(exception &e){              // 通过基类引用捕获所有派生异常
        // 调用虚函数what()获取异常描述
        cout << e.what() << endl;     // 输出:除数为0
    }
    return 0;                         // 程序正常退出
}

3.5 自定义异常

实现步骤:
继承自std::exception或其子类。
重写what()方法,返回错误描述(需保证返回的字符串有效性)。

#include<iostream>      // 输入输出流头文件
using namespace std;    // 标准命名空间

// 自定义异常类(继承标准异常体系)
class MyExcept:public exception{  // 继承自exception基类
public:
    // 异常描述方法(符合C++标准异常规范)
    // 第一个const: 返回不可修改的字符串指针
    // 第二个const: 承诺不修改对象状态
    // throw(): 空异常规格(C++11前表示不抛出任何异常)
    const char * what() const throw(){  // 重写虚函数
        return "除数为0";               // 返回固定错误描述
    }
};

// 带异常检查的除法运算
int divs(int a, int b)
{
    if(b == 0){              // 检查除数合法性
        MyExcept me;        // 创建异常对象实例
        throw me;           // 抛出符合标准的异常对象
    }
    return a/b;            // 执行安全除法运算
}

int main()
{
    try{                               // 异常监控代码块
        cout << divs(4, 0) << endl;    // 触发异常的调用点
    }
    catch(exception &e){              // 多态捕获标准异常体系
        cout << e.what() << endl;     // 通过虚函数获取描述信息
    }
    return 0;                         // 程序正常退出
}

四、文件流

头文件

#include <fstream>  // 包含文件流操作所需的类
#include <iostream> // 用于错误输出(如 cerr)
#include <string>   // 用于字符串处理

核心类
ofstream: 输出文件流,用于写入文件(默认模式:ios::out)。
ifstream: 输入文件流,用于读取文件(默认模式:ios::in)。
fstream: 多功能文件流,支持读写(需手动指定模式)。

#include<iostream>      // 输入输出流头文件
#include <fstream>      // 文件流操作头文件
using namespace std;    // 标准命名空间

int main()
{
    // 1. 文件打开操作
    // 以二进制模式打开源文件(注意相对路径的基准目录)
    ifstream inf("../25011test/mystring.cpp", ios_base::binary);
    if(!inf){  // 文件打开失败处理
        cout << "打开读文件失败" << endl;
        return 1;  // 立即终止程序
    }
    
    // 以二进制模式创建/覆盖目标文件
    ofstream outf("../25011test/test.cpp", ios_base::binary);
    if(!outf){  // 文件创建失败处理
        cout << "打开写文件失败" << endl;
        return 1;  // 立即终止程序
    }

    // 2. 文件读写操作
    char buf[32] = "";            // 固定缓冲区(存在溢出风险)
    inf.read(buf, 31);            // 读取最多31字节(预留结尾空字符)
    cout << buf << endl;          // 输出到控制台(二进制数据可能乱码)
    
    // 精确写入实际读取的字节数
    outf.write(buf, inf.gcount());  // gcount()获取最后一次读取的字节数

    // 3. 资源清理
    inf.close();     // 关闭输入文件流(可省略,析构时自动关闭)
    outf.close();    // 关闭输出文件流(同上)
    return 0;        // 正常退出程序
}

练习: 实现文件复制

#include<iostream>      // 输入输出流头文件
#include <fstream>      // 文件流操作头文件
using namespace std;    // 标准命名空间

int main()
{
    // 1. 文件打开操作
    // 以二进制模式打开源文件(注意相对路径的基准目录)
    ifstream inf("../25011test/mystring.cpp", ios_base::binary);
    if(!inf){  // 文件打开失败处理
        cout << "打开读文件失败" << endl;
        return 1;  // 立即终止程序(新增错误处理)
    }
    
    // 以二进制模式创建/覆盖目标文件
    ofstream outf("../25011test/test.cpp", ios_base::binary);
    if(!outf){  // 文件创建失败处理
        cout << "打开写文件失败" << endl;
        return 1;  // 立即终止程序(新增错误处理)
    }

    // 2. 文件读写操作
    char buf[32] = "";            // 固定缓冲区(32字节容量)
    while(true){                 // 循环读取直到文件结束
        inf.read(buf, 31);       // 每次读取31字节(预留空字符位)
        
        // 检测实际读取字节数(0表示到达文件末尾)
        if(inf.gcount() == 0)    // gcount()获取最后一次读取的字节数
            break;
            
        outf.write(buf, inf.gcount());  // 精确写入实际读取的字节数
    }

    // 3. 资源清理(可省略,析构时会自动关闭)
    inf.close();     // 显式关闭输入文件流
    outf.close();    // 显式关闭输出文件流
    return 0;        // 正常退出程序
}

总结

本文系统讲解C++模板机制实现泛型编程的原理,涵盖函数模板与类模板的语法特性及代码实践,深入剖析STL容器分类(顺序容器、关联容器)及其底层数据结构差异,通过vector、list、map等典型容器演示增删查改操作,详细解析异常处理流程包括标准异常与自定义异常实现,最后结合文件流操作示例展示二进制读写与安全处理方案,全面覆盖C++高效编程核心知识点。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2374538.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

在 Elasticsearch 中连接两个索引

作者&#xff1a;来自 Elastic Kofi Bartlett 解释如何使用 terms query 和 enrich processor 来连接 Elasticsearch 中的两个索引。 更多有关连接两个索引的查询&#xff0c;请参阅文章 “Elastic&#xff1a;开发者上手指南” 中的 “丰富数据及 lookup” 章节。 Elasticsea…

使用 Watt toolkit 加速 git clone

一、前言 Watt toolkit 工具是我经常用于加速 GitHub 网页和 Steam 游戏商店访问的工具&#xff0c;最近想加速 git clone&#xff0c;发现可以使用 Watt toolkit 工具的代理实现。 二、查看端口 我这里以 Ubuntu 为例&#xff0c;首先是需要将加速模式设置为 System&#xff1…

应急响应靶机——WhereIS?

用户名及密码&#xff1a;zgsf/zgsf 下载资源还有个解题.exe: 1、攻击者的两个ip地址 2、flag1和flag2 3、后门程序进程名称 4、攻击者的提权方式(输入程序名称即可) 之前的命令&#xff1a; 1、攻击者的两个ip地址 先获得root权限&#xff0c;查看一下历史命令记录&#x…

Docke容器下JAVA系统时间与Linux服务器时间不一致问题解决办法

本篇文章主要讲解&#xff0c;通过docker部署jar包运行环境后出现java系统内时间与服务器、个人电脑真实时间不一致的问题原因及解决办法。 作者&#xff1a;任聪聪 日期&#xff1a;2025年5月12日 问题现象&#xff1a; 说明&#xff1a;与实际时间不符&#xff0c;同时与服务…

【MCP】其他MCP服务((GitHub)

【MCP】其他MCP服务&#xff08;&#xff08;GitHub&#xff09; 1、其他MCP服务&#xff08;GitHub&#xff09; MCP广场&#xff1a;https://www.modelscope.cn/mcp 1、其他MCP服务&#xff08;GitHub&#xff09; 打开MCP广场 找到github服务 访问github生成令牌 先…

内存 -- Linux内核内存分配机制

内存可以怎么用&#xff1f; kmalloc&#xff1a;内核最常用&#xff0c;用于频繁使用的小内存申请 alloc_pages&#xff1a;以页框为单位申请&#xff0c;物理内存连续 vmalloc&#xff1a;虚拟地址连续的内存块&#xff0c;物理地址不连线 dma_alloc_coherent&#xff1a;常…

关于读写锁的一些理解

同一线程的两种情况&#xff1a; 读读&#xff1a; public static void main(String[] args) throws InterruptedException {ReentrantReadWriteLock lock new ReentrantReadWriteLock();Lock readLock lock.readLock();Lock writeLock lock.writeLock();readLock.lock();S…

C++修炼:模板进阶

Hello大家好&#xff01;很高兴我们又见面啦&#xff01;给生活添点passion&#xff0c;开始今天的编程之路&#xff01; 我的博客&#xff1a;<但凡. 我的专栏&#xff1a;《编程之路》、《数据结构与算法之美》、《题海拾贝》、《C修炼之路》 欢迎点赞&#xff0c;关注&am…

android-ndk开发(10): use of undeclared identifier ‘pthread_getname_np‘

1. 报错描述 使用 pthread 获取线程名字&#xff0c; 用到 pthread_getname_np 函数。 交叉编译到 Android NDK 时链接报错 test_pthread.cpp:19:5: error: use of undeclared identifier pthread_getname_np19 | pthread_getname_np(thread_id, thread_name, sizeof(thr…

UI自动化测试框架:PO 模式+数据驱动

&#x1f345; 点击文末小卡片&#xff0c;免费获取软件测试全套资料&#xff0c;资料在手&#xff0c;涨薪更快 1. PO 设计模式简介 什么是 PO 模式&#xff1f; PO&#xff08;PageObject&#xff09;设计模式将某个页面的所有元素对象定位和对元素对象的操作封装成…

Java笔记4

第一章 static关键字 2.1 概述 以前我们定义过如下类&#xff1a; public class Student {// 成员变量public String name;public char sex; // 男 女public int age;// 无参数构造方法public Student() {}// 有参数构造方法public Student(String a) {} }我们已经知道面向…

2025年渗透测试面试题总结-渗透测试红队面试八(题目+回答)

网络安全领域各种资源&#xff0c;学习文档&#xff0c;以及工具分享、前沿信息分享、POC、EXP分享。不定期分享各种好玩的项目及好用的工具&#xff0c;欢迎关注。 目录 渗透测试红队面试八 二百一十一、常见中间件解析漏洞利用方式 二百一十二、MySQL用户密码存储与加密 …

MiniMind:3块钱成本 + 2小时!训练自己的0.02B的大模型。minimind源码解读、MOE架构

大家好&#xff0c;我是此林。 目录 1. 前言 2. minimind模型源码解读 1. MiniMind Config部分 1.1. 基础参数 1.2. MOE配置 2. MiniMind Model 部分 2.1. MiniMindForCausalLM: 用于语言建模任务 2.2. 主干模型 MiniMindModel 2.3. MiniMindBlock: 模型的基本构建块…

如何进行前端性能测试?--性能标准

如何进行前端性能测试&#xff1f;–性能标准 前端性能测试指标&#xff1a; 首次加载阶段 场景&#xff1a;用户首次访问网页&#xff0c;在页面还未完全呈现各种内容和功能时的体验。重要指标及原因 首次内容绘制&#xff08;FCP - First Contentful Paint&#xff09;​…

通信网络编程——JAVA

1.计算机网络 IP 定义与作用 &#xff1a;IP 地址是在网络中用于标识设备的数字标签&#xff0c;它允许网络中的设备之间相互定位和通信。每一个设备在特定网络环境下都有一个唯一的 IP 地址&#xff0c;以此来确定其在网络中的位置。 分类 &#xff1a;常见的 IP 地址分为 I…

Off-Policy策略演员评论家算法SAC详解:python从零实现

引言 软演员评论家&#xff08;SAC&#xff09;是一种最先进的Off-Policy策略演员评论家算法&#xff0c;专为连续动作空间设计。它在 DDPG、TD3 的基础上进行了显著改进&#xff0c;并引入了最大熵强化学习的原则。其目标是学习一种策略&#xff0c;不仅最大化预期累积奖励&a…

热门CPS联盟小程序聚合平台与CPA推广系统开发搭建:助力流量变现与用户增长

一、行业趋势&#xff1a;CPS与CPA模式成流量变现核心 在移动互联网流量红利见顶的背景下&#xff0c;CPS&#xff08;按销售付费&#xff09;和CPA&#xff08;按行为付费&#xff09;模式因其精准的投放效果和可控的成本&#xff0c;成为企业拉新与用户增长的核心工具。 CPS…

Linux系统管理与编程15:vscode与Linux连接进行shell开发

兰生幽谷&#xff0c;不为莫服而不芳&#xff1b; 君子行义&#xff0c;不为莫知而止休。 【1】打开vscode 【2】点击左下角连接图标 【3】输入远程连接 选择合适的操作系统 输入密码&#xff0c;就进入Linux环境的shell编程了。 在vscode下面粘贴拷贝更方便。比如 然后在v…

RabbitMQ概念详解

什么是消息队列&#xff1f; 消息队列是一种在应用程序之间传递消息的技术。它提供了一种异步通信模式&#xff0c;允许应用程序在不同的时间处理消 息。消息队列通常用于解耦应用程序&#xff0c;以便它们可以独立地扩展和修改。在消息队列中&#xff0c;消息发送者将消息发送…

linux基础操作5------(shell)

一.前言 本文来介绍一下linux的shell&#xff0c;除了最后的那个快捷键&#xff0c;其他的还是做一个了解就行了。 Shell&#xff1a; 蛋壳的意思&#xff0c;是linux中比较重要的一个概念&#xff0c;所有的命令其实都称之为shell命令。 看图解&#xff1a;shell就是内核的一…