c->c++(三):stl

news2024/9/21 16:30:25

        本文主要探讨c++的stl相关知识:模版,容器,泛型算法,萃取特化,智能指针等。

模版
        
模板typename和class均可定义
        模板参数可是类型,还可是值
        模板编译根据调用实参类型推导参数类型
        编译器用值的类型实例化模板,用指针类型实例化模板,去除const修饰
        float,class-type类型对象,内链接对象作为非类型模板参数

容器
        
容器类=数据结构 + 算法
        序列容器:位置与元素值无关:array、vector、deque、list、forward_list
        关联容器:数据插入时自动从小到大排列:set、multiset、map、mutilmap
        无序关联容器:元素未排序的:unordered_set,unordered_mapunordered_multiset,unordered_multimap
        array:固定数组,可随机访问,不能添加或删除元素
        vector:可变数组,可随机访问,尾部外位置插入或删除元素慢
        string:存储字符,可随机访问,尾部插入或删除快(大小可变)
        deque:双端队列,可随机访问,头尾插入或删除快
        forward_list:单链表,可单顺序访问,任何位置插入或删除快
        list:双向链表,可双向顺序访问,任何位置插入或删除快
        set:有序容器,元素在集合中是唯一,用红黑树实现,插入、删除和查找时间复杂度为(log n)
        map:有序键值对容器,键在 map 中是唯一且键值唯一,用红黑树实现,插入、删除和查找操时间复杂度为(log n)
        multimap:关键字可重复出现的map
        multiset:关键字可重复出现的set

        arry
                
array是固定大小数组容器,默认构造非空
                长度为零时array.begin() == array.end(),拥有唯一值,front()和back()未定义
                swap时迭代器指向同一array元素并将改变元素的值
                begin()返回首元素迭代器,end()返回尾元素迭代器,rbegin()返回尾元素逆向迭代器,rend()返回首元素逆向迭代器,cbegin()同begin(),cend()同end(),crbegin()同rbegin(),crend()同rend(),增加了 const 属性
                size()返回当前元素数量(N)同max_size(),empty()判断容器是否为空
                at(n)返回元素n引用且检查越界抛出异常out_of_range,front()返回首元素引用,back()返回末尾元素引用,data()返回首元素指针
                fill(n)设置每个元素值为n,m.swap(n)交换m和n中所有元素(长度和类型相同),swap(m,n)交换m和n中所有元素
                operator==检查是否有相同数量元素且同位置元素是否相等
        重载get()全局函数访问容器指定元素并返回引用

        Vector
                
动态数组序列容器,元素连续存储可通过迭代器和指针访问元素
                assign()替换容器中的内容
                max_size()返回理论上的最大值
                reserve()修改容器容量
                capacity()返回当前分配的存储容量
                shrink_to_fit()清除未使用的容量
                clear()清除所有元素
                insert()指定位置插入元素,返回插首元素的迭代器
                emplace()在位置前插入元素,返回插入元素的迭代器
                erase()清除指定的元素
                push_back()追加元素到容器尾部
                emplace_back()在容器末尾构造元素(调用构造函数)
                pop_bak()移除末尾元素
                resize()改变元素大小

        string
                
operator=初始化字符串
                c_str返回c风格的字符串
                size(),length()字符串大小
                append(),operator+=追加的字符串尾部
                replace()替换字符串
                find()查找字符串
                find_first_of()寻找字符首次出现的位置,找到返回字符位置,找不到返回npos
                find_last_of()寻找字符最后次出现的位置
                find_first_not_of()寻找字符首次丢失的位置
                find_last_not_of()寻找字符最后丢失的位置
                stoi,stol,stoll转换字符串为有符号整数
                stoul,stoull转换字符串为无符号整数
                stof,stod,stold转换字符串为浮点值
                to_string转换整数或浮点值为string
                to_wstring转换整数或浮点值为wstring

        
        deque
                
有索引序列容器,允许首尾插入及删除
                与vector相反,deque元素不连续,按需扩张
                push_front()前附给定元素到容器起始
                emplace_front()在容器起始构造元素(调用构造函数)
                pop_front()移除容器首元素

       forward_list
                
单链表,任何位置插入和移除元素,不支持随机访问
                before_begin(),cbefore_begin()返回指向首元素前一元素迭代器,此元素表现为占位符,试图访问会导致未定义行为
                insert_after()在位置元素后插入
                emplace_after()在容器末尾构造元素(调用构造函数)
                erase_after()从容器移除指定元素
                merge()链表合并,other与this指一对象时没有操作,被合并链表为空
                splice_after()从另一forward_list移动元素到*this,元素插入指向元素后,被移动元素的链表缺少该元素
                remove(),remove_if()移除所有满足标准元素,只有指向被移除元素迭代器和引用会失效
                reserve()逆转元素顺序,迭代器和引用不会失效
                unique()删除连续重复元素
                sort()排序元素(升序),不会导致迭代器和引用失效

        list
                
带头双向循环链表,任意位置进行插入和删除,不支持[]随机访问

        set
               
 关联容器,含有Key类型对象排序集
                count()返回有key元素数(0,1)
                find()寻找键key元素,返回值指向元素迭代器,未找到则返回尾后迭代器
                contains()检查容器是否有key
                equal_range()返回键元素范围,范围有两个迭代器(该元素迭代器以及下一元素迭代器)
                lower_bound()返回指向首个>=key 元素迭代器
                upper_bound()返回指向首个<=key 元素迭代器

        map
                
有序关联容器,包含具有唯一键键值对,map实现为红黑树
                insert_or_assign() key存在则赋值给当前key,不存在则建立key在赋值
                emplace_hint()向容器中尽可能接近紧接元素之前的位置插入新元素

        multiset:Key类型对象有序集,允许多个Key有相同值
        multimap:关联容器,键值对已排序列表,多个元素可拥有同一键

        unordered_set
                
无序关联容器
                bucket_count()返回容器中的桶数
                max_bucket_count()返回容器最大桶数
                bucket_size()返回桶中的元素数
                bucket()返回键key桶索引
                load_factor()返回平均每桶元素数即size()/bucket_count()
                max_load_factor()管理最大加载因子(每个桶的平均元素数),加载因子超出阈值,增加桶数,返回最大加载因子
                rehash()设置桶数为不小于count且>=size()/max_load_factor()
                reserve()设置桶数至少count个元素且不超出最大加载因子

        unordered_map:无序关联容器,有带唯一键的键值对
        unordered_multiset:键的集合,按照键生成散列
        unordered_multimap:键值对的集合,按照键生成散列
        stack:适配一个容器以提供栈
        queue:适配一个容器以提供队列
        priority_queue:适配一个容器以提供优先级队列
        flat_set:调整容器以提供按键排序的唯一键集合
        flat_map:适配两个容器以提供按唯一键排序的键值对集合
        flat_multiset:调整容器以提供按关键字排序的关键字集合
        flat_multimap:适配两个容器以提供按键排序的键值对集合
        span:连续的对象序列上的无所有权视图
        mdspan:多维非拥有数组视图

泛型算法
        
容器是数据封装,泛型算法是数据操作方法
        谓词函数,数据操作函数:函数,函数指针,lambda,函数对象
        lambda:[捕获] (传参) mutable或exception声明 ->返回类型 {}
        最简lambda:[](){},调用:[](){}();
        lambda捕获列表
        []:不捕获
        [=]值捕获包括所在类的this
        [&]引用捕获包括所在类this
        [this]捕获所在类this
        [a]值捕获a
        [&a]引用捕获a
        [a,&b]值捕获a,引用捕获b
        [=,&a,&b]引用捕获a和b其余值捕获
        [&,a,b]值捕获a和b其余引用捕获

        不修改序列操作
                
for_each(first,last,fun)对范围[first,last)中迭代器解引用传给函数对象fun
                all_of(first,last,fun)对范围[first,last)中迭代器解引用传给函数对象fun,所有元素满足func返回true
                none_of(first,last,fun)对范围[first,last)中迭代器解引用传给函数对象fun,所有元素不满足func返回true
                any_of(first,last,fun)对范围[first,last)中迭代器解引用传给函数对象fun,有元素满足func返回true
                find(first,last,num)对范围[first,last)中迭代器解引用传给函数对象fun,有元素等于num返回该元素迭代器
                find_if(first,last,fun)对范围[first,last)中迭代器解引用传给函数对象fun,有元素满足fun返回该元素迭代器
                find_if_not(first,last,fun)对范围[first,last)中迭代器解引用传给函数对象fun,有元素不满足fun返回该元素迭代器
                find_end(first,last,f,l,fun)在范围[first, last)中搜索范围[f,s)经过fun处理元素迭代器
                find_first_of(first,last,f,l,fun)在范围 [first, last)中搜索范围[f,l)经过fun处理元素,返回搜索到的第一个元素迭代器
                count/count_if(first,last,fun/num)返回范围[first, last中满足fun/num元素数
                mismatch(first,last,f,l)返回两个范围内首次出现不同的元素
                search(first,last,f,l,fun)在范围 [first, last)中搜索范围[f,l)经过fun处理元素,返回搜索到的第一个元素迭代器
                serach_n在范围[first,last,count,value,fun)中搜索count个等同元素的序列,每个都等于给定的值 value,fun(*first,value),返回搜索到的第一个元素迭代器

        修改序列的操作
                
copy(first,last,f)/copy_if(first,last,f,fun)复制范围[first, last)中的元素到从f开始的另一范围,返回目标最后下一个元素输出迭代器
                copy_n(frist,num,f)从first开始复制num个元素到f开始的地方,返回目标最后下一个元素输出迭代器否则返回f
                copy_backward(first,last,l)复制范围[first, last)中的元素到范围尾部(l为尾部迭代器),返回最后复制的元素
                move(first,last,f)复制范围[first, last)中的元素到从f开始的另一范围,返回目标最后下一个元素输出迭代器
                move_bakcward(first,last,l)复制范围[first, last)中的元素到范围尾部(l为尾部迭代器),返回最后复制的元素
                swap(a,b)交换a,b,iter_swap(a,b)交换两个迭代器指向的元素
                swap_ranges(first,last,f)交换范围[first,last)中的元素到从f开始的另一范围
                replace(first,last,old,new)/replace_if(first,last,fun,new)替换来自范围[first, last)的元素到始于f范围,复制过程中以new(fun(*first))替换所有满足特定判别标准的元素
                replace_copy_if(first,last,f,fun,new)复制来自范围[first, last)的元素到始于f范围,复制过程中以new(fun(*first)) 替换所有满足特定判别标准的元素
                fill(first,last,num)用num填充范围[first, last)的元素
                fill(first,count,num)用num填充起始范围first的count个元素值为num
                generate(first,last,fun)将fun产生的数赋值给[first, last)的元素
                generate(first,count,fun)将fun产生的数赋值给first起始的count个元素
                remove(first,last,value)/remove_if(first,last,fun)移除范围内value或fun返回值
                remove_copy(first,last,f,value)/remove_copy_if(first,last,f,fun)复制范围内的元素到f,并移除value或fun返回值
                unique_copy(first, last,f)从范围[first, last)复制元素到从f开始的另一范围,使得目标范围不存在连续的相等元素
                reverse(first, last)/reverse_copy(first, last,f)反序
                rotate_copy(first,n_f,last,f)从范围[first, last)复制元素到始于f的另一范围,使得 *n_f成为新范围的首元素而 *(n_f-1)为末元素

        排序操作
                
sort将范围按升序排序
                stable_sort将范围内的元素排序,同时保持相等的元素之间的顺序
                partial_sort排序一个范围的前 N 个元素
                partial_sort_copy对范围内的元素进行复制并部分排序
                is_sorted检查范围是否已按升序排列
                is_sorted_until找出最大的有序子范围
                nth_element将给定的范围部分排序,确保其按给定元素划分

        二分搜索操作
                
lower_bound返回指向第一个不小于给定值的元素的迭代器
                upper_bound返回指向第一个大于给定值的元素的迭代器
                equal_range返回匹配特定键值的元素范围
                binary_search确定元素是否存在于某部分有序的范围中

        集合操作
                
includes若一个序列是另一个的子序列则返回 true
                set_union计算两个集合的并集
                set_intersection计算两个集合的交集
                set_difference计算两个集合的差集
                set_symmetric_difference计算两个集合的对称差

        归并操作
               
 merge合并两个有序范围
                inplace_merge就地合并两个有序范围

        堆操作
               
 push_heap将一个元素加入到一个最大堆
                pop_heap从最大堆中移除最大元素
                make_heap从一个元素范围创建出一个最大堆
                sort_heap将一个最大堆变成一个按升序排序的元素范围
                is_heap检查给定范围是否为一个最大堆
                is_heap_until查找能成为最大堆的最大子范围

        最小/最大操作
                
max返回各给定值中的较大者
                max_element返回范围内的最大元素
                min返回各给定值中的较小者
                min_element返回范围内的最小元素
                minmax返回两个元素的较小和较大者
                minmax_element返回范围内的最小元素和最大元素

萃取和特化
       
 模板特化类似函数重载,编译链接时确定
        优先级:同名函数>全特化>偏特化>泛化
        全特化所有模板类型为具体类型
        偏特化部分特化原模板的类型
        区分T是源生类型或自定义类型
        POD(原生类型)int、double,char,float等,本质是没有高级特征(构造析构,虚函数等)
        POD memcpy可用,非POD类型需循环拷贝
        is_pod判断是否是pod类型

智能指针
      
  智能指针本身是类
        智能指针解决内存泄漏问题,连带自动释放内存
        智能指针本质原理:利用对象释放时会自动调用析构函数特性
        unique_ptr对象不可复制(=),可移动(move)
        unique_ptr同时间只指向一个对象,指向新对象时,之前对象被释放
        unique_ptr本身被释放时,对象也释放
        unique_ptr不能进行赋值和拷贝构造
        release()释放被管理对象的所有权,返回被管理对象指针,无被管理对象返回nullptr
        reset(对象)替换被管理对象,若旧对象为非空则调用删除器删除
        swap()交换被管理对象和关联删除器
        get()返回被管理对象指针,无对象返回nullptr
        get_deleter()返回会用于析构被管理对象的删除器对象
        shared_ptr基于引用计数设计,多个智能指针绑定1个对象
        shared_ptr使用构造函数或make_shared方法构造
        shared_ptr释放指针对象,调用Deleter,再调析构释放
        use_count()管理当前对象的shared_ptr实例数量
        unique()管理当前对象的shared_ptr实例数量为1(use_count() = 1)返回true否则false
        make_shared()创建管理一个新对象的共享指针
        weak_ptr不管理shared_ptr内部指针,没有*和->操作符
        weak_ptr不共享指针,不操作资源,构造和析构不影响引用计数
        weak_ptr监视shared_ptr中管理资源是否存在
        expired()管理对象删除为true否则为false(use_count() = 0)
        lock()若无共享对象返回false,否则返回shared_ptr对象
        reset()释放被管理对象的所有权(use_count() = 0)

demo1:

        模版

目录:

run.sh

#!/bin/bash

if [ -f ./Makefile ]
then
        make clean
fi

cmake .

make

echo "---------------------------------"

./pro

clean.sh

#!/bin/bash

rm -rf CMakeFiles pro Makefile CMakeCache.txt cmake_install.cmake

check_mem.sh

valgrind --tool=memcheck --leak-check=full --show-reachable=yes --trace-children=yes -s ./pro

CMakeLists.txt

CMAKE_MINIMUM_REQUIRED(VERSION 2.20)                            #最低版本要求

SET(CMAKE_CXX_COMPILER "g++-11")                                #设置g++编译器

set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g")                    #添加编译选项

PROJECT(CLASS)                                                  #设置工程名

MESSAGE(STATUS "template test")                                 #打印消息

ADD_EXECUTABLE(pro main.cpp)                                    #生成可执行文件

  main.cpp   

#include <iostream>

using namespace std;

template <typename T1,typename T2> 
class Person
{
        private:
                T1 argv1;
                T2 argv2;
        public:
                Person(){};
                Person(T1 argv1,T2 argv2);
                void printf_info();

                void operator+=(Person<T1,T2> p);
                template <typename U1,typename U2> 
                friend Person<U1,U2> operator+(Person<U1,U2> p1,Person<U1,U2> p2);

};

template <typename T1,typename T2>
class Man:public Person<T1,T2>
{
        public:
                T1 argv1;
                T2 argv2;
                Man(T1 argv1,T2 argv2):Person<T1,T2>(argv1,argv2),argv1(argv1),argv2(argv2){};
};

template <typename T1,typename T2> 
Person<T1,T2>::Person(T1 argv1,T2 argv2)
{
        this->argv1 = argv1;
        this->argv2 = argv2;
}

template <typename X,int ARRY_SIZE>
class Arry
{
        private:
                X ar[ARRY_SIZE] = {0};
        public:
                void set_arry();
                void printf_arry();

};

template <typename T1,typename T2>
void Person<T1,T2>::printf_info()
{
        string s = typeid(this->argv1).name();
        if(s == "i")
        {
                cout << "name :" << this->argv2  << endl;
                cout << "age :" << this->argv1  << endl;
        }
        else
        {
                cout << "name :" << this->argv1  << endl;
                cout << "age :" << this->argv2  << endl;
        }
}

template <typename T1,typename T2>
void Person<T1,T2>::operator+=(Person<T1,T2> p)
{
        this->argv1 += p.argv1;
        this->argv2 += p.argv2;
}

template <typename T1,typename T2>
Person<T1,T2> operator+(Person<T1,T2> p1,Person<T1,T2> p2)
{
        Person<T1,T2> tmp;
        tmp.argv1 = p1.argv1 + p2.argv1;
        tmp.argv2 = p1.argv2 + p2.argv2;
        return tmp;
}

template <typename X,int ARRY_SIZE>
void Arry<X,ARRY_SIZE>::set_arry()
{
        for(int i = 0;i < ARRY_SIZE ;i++)
                ar[i] = i;
}

template <typename X,int ARRY_SIZE>
void Arry<X,ARRY_SIZE>::printf_arry()
{
        for(int i = 0;i < ARRY_SIZE ;i++)
                cout << ar[i] << " ";
        cout << endl;
}

int main()
{
        Person<int,string> p1(10,"hello");
        Person<int,string> p2(10," word");
        Person<int,string> p3 = p1 + p2;
        Person<int,string> p4(10,"!");
        p3 += p4,
        p3.printf_info();

        Man<int,string> m(20,"xiaoming");
        m.printf_info();
        m.Person::printf_info();

        Arry<int,3> a;
        a.set_arry();
        a.printf_arry();

        return 0;
}

结果示例:

demo2:

        string

目录:

run.sh

#!/bin/bash

if [ -f ./Makefile ]
then
        make clean
fi

cmake .

make

echo "---------------------------------"

./pro

check_mem.sh

valgrind --tool=memcheck --leak-check=full --show-reachable=yes --trace-children=yes -s ./pro

clean.sh

#!/bin/bash

rm -rf CMakeFiles pro Makefile CMakeCache.txt cmake_install.cmake

CMakeLists.txt

CMAKE_MINIMUM_REQUIRED(VERSION 2.20)                            #最低版本要求

SET(CMAKE_CXX_COMPILER "g++-11")                                #设置g++编译器

set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g")                    #添加编译选项

PROJECT(CLASS)                                                  #设置工程名

MESSAGE(STATUS "string test")                                   #打印消息

ADD_EXECUTABLE(pro main.cpp)                                    #生成可执行文件

main.cpp

#include <iostream>
#include <cstdio>

using namespace std;

int main()
{
        string s = "hello word";
        cout << "s.size():" << s.size() << endl;
        cout << "s.length():" << s.length() << endl;
        s += "!!!";
        cout << "s:" << s << endl;

        const char *p = s.c_str();
        printf("s:%s\n",p); 

        auto f = s.find('w');
        s.replace(f,4,"cxb");
        cout << "s:" << s << endl;

        if (s.find_first_of('u') == string::npos)
                cout << "s have no 'u'" << endl;

        string str = s.substr(0,5);
        cout << "str:" << str << endl;

        string name;
        getline(cin,name);
        cout << "name:" << name << endl;

        int n = stoi("100");
        cout << "n(int):" << n << endl;
        string num = to_string(n);
        cout << "num(string):" << num << endl;

        return 0;
}

结果示例:

demo3:

        容器

目录:

run.sh

#!/bin/bash

if [ -f ./Makefile ]
then
        make clean
fi

cmake .

make

echo "---------------------------------"

./pro

check_mem.sh

valgrind --tool=memcheck --leak-check=full --show-reachable=yes --trace-children=yes -s ./pro

clean.sh

#!/bin/bash

rm -rf CMakeFiles pro Makefile CMakeCache.txt cmake_install.cmake

CMakeLists.txt

CMAKE_MINIMUM_REQUIRED(VERSION 2.20)                            #最低版本要求

SET(CMAKE_CXX_COMPILER "g++-11")                                #设置g++编译器

set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g")                    #添加编译选项

PROJECT(CLASS)                                                  #设置工程名

MESSAGE(STATUS "stl test")                                      #打印消息

set(SRC_LIST main.cpp array.cpp vector.cpp deque.cpp forward_list.cpp list.cpp set.cpp map.cpp unordered_set.cpp stack.cpp queue.cpp priority_queue.cpp unordered_multimap.cpp)

ADD_EXECUTABLE(pro ${SRC_LIST})                                         #生成可执行文件

main.cpp

#include <iostream>

#include "main.hpp"

using namespace std;

int main()
{
        cout << "----------------------stl_array---------------------" << endl;
        stl_array();
        cout << "----------------------stl_vector--------------------" << endl;
        stl_vector();
        cout << "----------------------stl_deque---------------------" << endl;
        stl_deque();
        cout << "----------------------stl_forward_list--------------" << endl;
        stl_forward_list();
        cout << "----------------------stl_list----------------------" << endl;
        stl_list();
        cout << "----------------------stl_set-----------------------" << endl;
        stl_set();
        cout << "----------------------stl_map-----------------------" << endl;
        stl_map();
        cout << "----------------------stl_unordered_set-------------" << endl;
        stl_unordered_set();
        cout << "----------------------stl_stack---------------------" << endl;
        stl_stack();
        cout << "----------------------stl_queue---------------------" << endl;
        stl_queue();
        cout << "----------------------stl_priority_queue------------" << endl;
        stl_priority_queue();
        cout << "----------------------stl_unordered_multimap--------" << endl;
        stl_unordered_multimap();
        return 0;
}

main.hpp

#ifndef __MAIN_HPP
#define __MAIN_HPP

void stl_array();
void stl_vector();
void stl_deque();
void stl_forward_list();
void stl_list();
void stl_set();
void stl_map();
void stl_unordered_set();
void stl_stack();
void stl_queue();
void stl_priority_queue();
void stl_unordered_multimap();

#endif

array.cpp

#include <iostream>
#include <array>

using namespace std;

void stl_array()
{
        array<int,3> a1 = {1,2,3};
        array<int,3> a2;
        array<int,3> a3;
        a2 = a1;
        cout << "a2.front:" << a2.front() << endl;
        cout << "a2[2]:" << a2[1] << endl;
        cout << "get<2>(a2):" << get<2>(a2) << endl;
        cout << "a2.back:" << a2.back() << endl;
        cout << "*(a2.data):" << *(a2.data()) << endl;
        cout << "a2.empty():" << boolalpha << a2.empty() << endl;
        cout << "a2.size():" << a2.size() << endl;
        cout << "a2.max_size():" << a2.max_size() << endl;
        cout << "a3.empty():" << boolalpha << a3.empty() << endl;
        cout << "a3.size():" << a3.size() << endl;
        cout << "a3.max_size():" << a3.max_size() << endl;

        cout << "a1:";
        for(auto i = a1.begin();i != a1.end();i++)
        {
                cout << *i << " "; 
        }
        cout << endl;

        cout << "a2:";
        for(auto i = 0;i < a2.size();i++)
        {
                cout << a2.at(i) << " ";
        }
        cout << endl;

        cout << "a2 reserve:";
        for(auto i = a2.rbegin();i != a2.rend();i++)
        {
                cout << *i << " ";
        }
        cout << endl;

        a3.fill(6);
        cout << "a3:";
        for(auto i = 0;i < a3.size();i++)
        {
                cout << a3.at(i) << " ";
        }
        cout << endl;

        cout << "swap a1 a3 : " << endl;
        a3.swap(a1);

        cout << "a3:";
        for(auto i = 0;i < a3.size();i++)
        {
                cout << a3.at(i) << " ";
        }
        cout << endl;

        cout << "a1:";
        for(auto i = a1.begin();i != a1.end();i++)
        {
                cout << *i << " ";
        }
        cout << endl;
}

deque.cpp

#include <iostream>
#include <deque>

using namespace std;

template <typename T>
static void printf_queue(T const& q)
{
        for(auto i : q)
                cout << i << " ";
        cout << endl;
}

void stl_deque()
{
        deque<int> num;
        num.push_front(1);
        num.push_front(2);
        num.push_front(3);
        num.emplace_front(4);
        num.emplace_front(5);
        num.emplace_front(6);
        cout << "num:";
        printf_queue(num);
        cout << "pop_front num:";
        num.pop_front();
        printf_queue(num);

}

forward_list.cpp

#include <iostream>
#include <forward_list>

using namespace std;

template<typename T>
static void printf_forward_list(T const& n)
{
        for(auto i : n)
                cout << i << " ";
        cout << endl;
}

void stl_forward_list()
{
        forward_list<int> num;
        forward_list<int> tmp = {7,8,9,10};
        forward_list<int> num1 = {7,8,9,10};

        num.insert_after(num.before_begin(),1);
        num.insert_after(num.before_begin(),2);
        num.insert_after(num.before_begin(),3);
        cout << "insert_after num:" << endl;
        printf_forward_list(num);

        cout << "emplace_after num:";
        num.emplace_after(num.before_begin(),4);
        num.emplace_after(num.before_begin(),5);
        num.emplace_after(num.before_begin(),6);
        printf_forward_list(num);

        cout << "tmp:";
        printf_forward_list(tmp);

        cout << "num.splice_after(num.before_begin(),tmp)" << endl;
        num.splice_after(num.before_begin(),tmp);
        cout << "tmp :";
        printf_forward_list(tmp);
        cout << "num :";
        printf_forward_list(num);

        cout << "num1:";
        printf_forward_list(num1);

        cout << "num.merge(num1)" << endl;
        num.merge(num1);
        cout << "num1:";
        printf_forward_list(num1);
        cout << "num:";
        printf_forward_list(num);

        cout << "sort num:";
        num.sort();
        printf_forward_list(num);

        cout << "unique num:";
        num.unique();
        printf_forward_list(num);

        cout << "reverse num:";
        num.reverse();
        printf_forward_list(num);

        cout << "remove num:";
        num.remove(10);
        printf_forward_list(num);

        cout << "erase_after num:";
        num.erase_after(num.before_begin());
        printf_forward_list(num);

        cout << "num.erase_after(fi,la):";
        auto fi = next(num.begin());
        auto la = next(fi, 3);
        cout << "fi:" << *(fi) << endl;
        cout << "la:" << *(la) << endl;
        num.erase_after(fi,la);
        printf_forward_list(num);
}

list.cpp

#include <iostream>
#include <list>

using namespace std;

template <typename T>
static void printf_list(T const& l)
{
        for(auto i : l)
                cout << i << " ";
        cout << endl;
}

void stl_list()
{
        list<int> num;
        num.push_front(1);
        num.push_front(2);
        num.push_front(3);
        num.emplace_front(4);
        num.emplace_front(5);
        num.emplace_front(6);
        cout << "num:";
        printf_list(num);
        cout << "pop_front num:";
        num.pop_front();
        printf_list(num);

}

map.cpp

#include <iostream>
#include <map>

using namespace std;

template<typename T>
static void printf_map(T const& m)
{
        for(auto [key,value] : m)
                cout << key << ":" << value << endl ;
}

void stl_map()
{
        map<string,string> m = {{"name","xiaoming"},{"income","100"}};
        m.insert(m.begin(),{"age","20"});
        cout << "map:" << endl;
        printf_map(m);
        m.insert_or_assign("saving_count","2000");
        m.insert_or_assign("income","1000");

        auto tmp = m.find("name");
        m.emplace_hint(tmp,"hobby","game");
        cout << "new map:" << endl;
        printf_map(m);

}

priority_queue.cpp

#include <iostream>
#include <queue>

using namespace std;

void stl_priority_queue()
{
        priority_queue<int> p;

        p.push(1);
        p.push(8);
        p.push(5);
        p.push(3);
        p.push(2);

        cout << "priority_queue:";
        while(p.size())
        {
                cout << p.top() << " ";
                p.pop();
        }
        cout << endl;
}

queue.cpp

#include <iostream>
#include <queue>

using namespace std;

void stl_queue()
{

        queue<string> q;
        q.push("linux");
        q.push("windows");
        q.push("macos");
        q.push("android");
        q.push("harmonyos");

        cout << "queue front :" << q.front() << endl;
        cout << "queue back :" << q.back() << endl;

        cout << "queue :";
        while(!q.empty())
        {
                cout << q.front() << " ";
                q.pop();
        }
        cout << endl;
}

set.cpp

#include <iostream>
#include <set>

using namespace std;

template<typename T>
static void printf_set(T const& s)
{
        for(auto i : s)
                cout << i << " ";
        cout << endl;
}

void stl_set()
{
        set<int> s;
        s.insert(s.begin(),1);
        s.insert(s.begin(),1);
        s.insert(s.begin(),1);
        s.insert(s.begin(),2);
        s.insert(s.begin(),3);

        cout << "set :" ;
        printf_set(s);

        if(s.count(1))
                cout << "set has 1 :" << s.count(1) << endl;

        auto tmp = s.find(2);
        if(tmp != s.end())
                cout << "set has 2" << endl;

        auto [b,e] = s.equal_range(2);
        cout << "b = s.equal_range(2):" << *b << endl;
        cout << "e = s.equal_range(2):" << *e << endl;
        cout << "s.lower_bound():" << *(s.lower_bound(2)) << endl;
        cout << "s.upper_bound():" << *(s.upper_bound(2)) << endl;
}

stack.cpp

#include <iostream>
#include <stack>

using namespace std;

void stl_stack()
{
        stack<int> s;
        s.push(1);
        s.push(2);
        s.push(3);
        s.push(4);
        s.push(5);

        cout << "stack :";
        while(s.size() != 0)
        {
                cout << s.top() << " ";
                s.pop();
        }
        cout << endl;
}

unordered_multimap.cpp

#include <iostream>
#include <unordered_map>

using namespace std;

template<typename T>
static void print_unordered_multimap(T const& p)
{
        for(auto i : p)
        {
                cout << "(" << i.first << "," << i.second << ")" << endl;
        }
}

void stl_unordered_multimap()
{
        unordered_multimap<int,string> p;
        for(auto i = 0;i < 20;i++)
        {
                p.insert({i,"hello"});
                cout << "{"<< i << ",helllo}  " << "em size:"  << p.size() << ",bucket size:" << p.bucket_count() << endl;
        }

        print_unordered_multimap(p);

        cout << "p.bucket_size(p.bucket(1)):" << p.bucket_size(p.bucket(1)) << endl;
}

unordered_set.cpp

#include <iostream>
#include <unordered_set>

using namespace std;

template<typename T>
static void printf_unordered_set(T const& us)
{
        for(auto i : us)
                cout << i << " ";
        cout << endl;
}

void stl_unordered_set()
{
        unordered_set<int> us;
        for(auto i = 0;i < 100;i++)
        {
                us.insert(i);
        }
        cout << "unordered_set:";
        printf_unordered_set(us);

        cout << "bucket_count:" << us.bucket_count() << endl;
        cout << "max_bucket_count:" << us.max_bucket_count() << endl;
        cout << "us.load_factor():" << us.load_factor() << endl;
        cout << "us.max_load_factor():" << us.max_load_factor() << endl;

        cout << "new unordered_set(us.rehash(10) us.reserve(3)):";
        us.rehash(10);
        us.reserve(3);
        printf_unordered_set(us);
        cout << "bucket_count:" << us.bucket_count() << endl;
        cout << "max_bucket_count:" << us.max_bucket_count() << endl;
        cout << "us.load_factor():" << us.load_factor() << endl;
        cout << "us.max_load_factor():" << us.max_load_factor() << endl;

}

vector.cpp

#include <iostream>
#include <vector>

using namespace std;

template <typename T>
static void printf_sentence(T const &s)
{
        for(auto i : s)
                cout << i ;
        cout << endl;
        cout << "sentence.capacity:" << s.capacity() << endl;
        cout << "sentence.size:" << s.size() << endl;
        cout << "sentence.max_size:" << s.max_size() << endl;
}

void stl_vector()
{
        vector <char> sentence;
        sentence.push_back('h');
        sentence.push_back('e');
        sentence.push_back('l');
        sentence.push_back('l');
        sentence.push_back('o');
        sentence.push_back('\n');
        cout << "sentence :";
        printf_sentence(sentence);

        cout << "assign sentence :";
        sentence.assign({'w','o','r','d','!'});
        printf_sentence(sentence);

        cout << "insert sentence :";
        sentence.insert(sentence.begin(),{'h','e','l','l','o',' '});
        printf_sentence(sentence);

        cout << "emplace sentence :";
        sentence.emplace(sentence.end(),'!');
        printf_sentence(sentence);

        cout << "earse sentence :";
        sentence.erase(sentence.end()-1); 
        sentence.erase(sentence.begin(),sentence.begin()+6);
        printf_sentence(sentence);

        cout << "emplace_back sentence :";
        sentence.emplace_back('?');
        printf_sentence(sentence);

        cout << "pop_back sentence :";
        sentence.pop_back();
        printf_sentence(sentence);

        cout << "resize sentence :";
        sentence.resize(10);
        printf_sentence(sentence);

        cout << "shrink_to_fit sentence :";
        sentence.shrink_to_fit();
        printf_sentence(sentence);

        cout << "clear sentence :";
        sentence.clear();
        printf_sentence(sentence);
}

结果示例:

demo4:

        泛型算法

目录:

 run.sh

#!/bin/bash

if [ -f ./Makefile ]
then
        make clean
fi

cmake .

make

echo "---------------------------------"

./pro

check_mem.sh

valgrind --tool=memcheck --leak-check=full --show-reachable=yes --trace-children=yes -s ./pro

clean.sh

#!/bin/bash

rm -rf CMakeFiles pro Makefile CMakeCache.txt cmake_install.cmake

CMakeLists.txt

CMAKE_MINIMUM_REQUIRED(VERSION 2.20)                            #最低版本要求

SET(CMAKE_CXX_COMPILER "g++-11")                                #设置g++编译器

set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g")                    #添加编译选项

PROJECT(CLASS)                                                  #设置工程名

MESSAGE(STATUS "string test")                                   #打印消息

ADD_EXECUTABLE(pro main.cpp)                                    #生成可执行文件

main.cpp

#include <iostream>
#include <vector>
#include <algorithm>
#include <iterator>

using namespace std;

template<typename T>
class gt
{
        public:
                bool operator()(const T& f,const T& l)
                {
                        return (f > l);
                }
};

template<typename T>
static void print_vector(const T& v)
{
        for(auto i : v)
                cout << i << " ";
        cout << endl;
}

auto even_num =  [](const int& n)->bool{return (n % 2 == 0);};

auto grater_10 =  [](const int& n){return (n > 10);};

int main()
{
        vector<int> a = {1,6,3,9,7};
        vector<int> b = {1,2,3,1,2,3,1,2,3};
        vector<int> c = {1,3,8};
        vector<int> d = {1,3,8};
        vector<int> e = {1,3,9};
        vector<int> f = {1,3,8};
        vector<int> g = {1,3,8};
        vector<int> h = {2,4,6};
        vector<int> j = {2,4,1,2,2,2,2,4};
        vector<int> k(6);

        cout << "for_earch(f++) bfore:";
        print_vector(a);
        for_each(a.begin(),a.end(),[](int& f){f++;});
        cout << "for_earch(f++) end:";
        print_vector(a);

        if(!(all_of(a.begin(),a.end(),even_num)))
                cout << "all_of have no even_num" << endl;
        if(any_of(a.begin(),a.end(),even_num))
                cout << "any_of have even_num" << endl;
        if(any_of(a.begin(),a.end(),grater_10))
                cout << "none have num grater 10" << endl;

        if(find(a.begin(),a.end(),10) != a.end())
                cout << "find 9" << endl;
        if(auto it = find_if(a.begin(),a.end(),even_num); it != a.end())
                cout << "find if :the first em support even_num func :" << *it << endl;
        if(auto it = find_if_not(a.begin(),a.end(),even_num); it != a.end())
                cout << "find if :the first em not support even_num func :" << *it << endl;

        for(auto t : {vector<int>{-1,-2,-3},{4,5,6}})
        {
                auto it = find_end(b.begin(),b.end(),t.begin(),t.end(),[](const int& bf,const int& tf) {return (abs(bf) == abs(tf));});
                if(it == b.end())
                {
                        cout << "{4,5,6} have no found" << endl;
                }
                else
                {
                        cout << "{1,2,3} last pos:" << distance(b.begin(),it)  << endl;
                }
        }

        auto it = find_first_of(a.begin(),a.end(),c.begin(),c.end(),[](int& af,int& cf) {return ((af) == (++cf));});
        if(it !=  a.end())
                cout << "the first em of find_first_of func : " << *it << endl;

        auto cn = count_if(a.begin(),b.begin(),even_num);
        cout << "the even_num's num of a: " << cn << endl; 

        pair< vector<int>::iterator,vector<int>::iterator > p;

        p = mismatch(d.begin(),d.end(),e.begin(),[](int& df,int& ef) {return ((++df) == (++ef));});
        cout << "mismatch ,the firstly different em in  two vector :" << *p.first << "," << *p.second  << endl;

        if(equal(f.begin(),f.end(),g.begin(),[](int& ff,int& gf) {return ((++ff) == (++gf));}))
                cout << "g is same of f" << endl;
        auto tmp = search(b.begin(),b.end(),h.begin(),h.end(),[](int& bf,int& hf) {return ((bf) == (hf/2));});
        cout << "{1,2,3} last pos:" << distance(b.begin(),tmp)  << endl;

        auto sn = search_n(j.begin(),j.end(),2,2,[](const int& jf,const int& v) ->bool {return (jf == v);});
        cout << "the first em pos:" << distance(j.begin(),sn) << endl;

        cout << "copy :";
        copy_if(a.begin(),a.end(),ostream_iterator<int>(cout," "),[](int& n){return(n %2 == 0);});
        cout << endl;
        cout << "copy_n :";
        copy_n(a.begin(),2,ostream_iterator<int>(cout," "));
        cout << endl;
        cout << "copy_backward :";
        copy_backward(a.begin(),a.end(),k.end());
        print_vector(k);

        cout << "move:";
        move(a.begin(),a.end(),ostream_iterator<int>(cout," "));
        cout << endl;
        cout << "move_backward:";
        move_backward(a.begin(),a.end(),k.end());
        print_vector(k);

        cout << "swap before b:";
        print_vector(b);
        cout << "swap before c:";
        print_vector(c);
        swap_ranges(c.begin(),c.end(),b.begin());
        cout << "swap after b:";
        print_vector(b);
        cout << "swap after c:";
        print_vector(c);
        cout << "transform:";
        transform(c.begin(),c.end(),c.begin(),c.begin(),[](const int& c1,const int c2){return (c1 + c2);});
        print_vector(c);

        cout << "replace_if:";
        replace_if(a.begin(),a.end(),even_num,2);
        print_vector(a);

        cout << "replace_copy_if:";
        replace_copy_if(a.begin(),a.end(),ostream_iterator<int>(cout," "),even_num,1);
        cout << endl;

        cout << "fill:";
        fill(a.begin(),a.end(),6);
        print_vector(a);

        cout << "fill_n:";
        fill_n(a.begin(),3,2);
        print_vector(a);

        cout << "generate:";
        generate(a.begin(),a.end(),[n = 0]() mutable {return n++;});
        print_vector(a);

        cout << "generate_n:";
        generate_n(ostream_iterator<int>(cout," "),3,[n = 0]() mutable {return n++;});
        cout << endl;

        cout << "remove:";
        a.erase(remove_if(a.begin(),a.end(),even_num),a.end());
        print_vector(a);

        cout << "remove_copy_if:";
        remove_copy_if(b.begin(),b.end(),ostream_iterator<int>(cout," "),even_num);
        cout << endl;

        cout << "uniqe before:";
        print_vector(j);
        unique(j.begin(),j.end());
        cout << "uniqe after:";
        print_vector(j);

        cout << "reverse:";
        reverse(j.begin(),j.end());
        print_vector(j);

        cout << "reverse_copy:";
        reverse_copy(j.begin(),j.end(),ostream_iterator<int>(cout," "));
        cout << endl;

        cout << "rotate:";
        rotate(j.begin(),j.begin()+1,j.end());
        print_vector(j);

        cout << "rotate_copy:";
        rotate_copy(j.begin(),j.begin()+3,j.end(),ostream_iterator<int>(cout," "));
        cout << endl;

        cout << "sort:";
        sort(j.begin(),j.end());
        print_vector(j);

        cout << "sort:";
        sort(j.begin(),j.end(),gt<int>());
        print_vector(j);

        cout << "stable_sort";
        struct people
        {
                int num;
                string name;
        };
        vector<people> pe{{2,"xiaoming"},{1,"xiaohua"},{2,"xiaoli"}};
        stable_sort(pe.begin(),pe.end(),[](const people& f,const people& l){return (f.num > l.num);});
        for(auto i : pe)
                cout << "{" << i.num << "," << i.name << "} ";
        cout << endl;

        cout << "upper_bound:";
        auto ub = upper_bound(c.begin(),c.end(),3);
        cout << *ub << endl;

        cout << "b:";
        sort(b.begin(),b.end());
        print_vector(b);
        cout << "c:";
        print_vector(c);
        cout << "merge:";
        merge(b.begin(),b.end(),c.begin(),c.end(),ostream_iterator<int>(cout," "));
        cout << endl;

        return 0;
}

执行结果:

demo5:

        特化萃取

目录:

run.sh

#!/bin/bash

if [ -f ./Makefile ]
then
        make clean
fi

cmake .

make

echo "---------------------------------"

./pro

clean.sh

#!/bin/bash

rm -rf CMakeFiles pro Makefile CMakeCache.txt cmake_install.cmake

check_mem.sh

valgrind --tool=memcheck --leak-check=full --show-reachable=yes --trace-children=yes -s ./pro

CMakeLists.txt

CMAKE_MINIMUM_REQUIRED(VERSION 2.20)                            #最低版本要求

SET(CMAKE_CXX_COMPILER "g++-11")                                #设置g++编译器

set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g")                    #添加编译选项

PROJECT(CLASS)                                                  #设置工程名

MESSAGE(STATUS "template test")                                 #打印消息

ADD_EXECUTABLE(pro main.cpp)                                    #生成可执行文件

main.cpp

#include <iostream>
#include <cstring>

using namespace std;

//函数模版
template<typename T>
void comp(const T& f,const T& l)
{
        if(f > l)
        {
                cout << f << " > " << l << endl;
        }
        else
        {
                cout << f << " < " << l << endl;
        }
}

//函数模版特化
template<>
void comp(const string& f,const string& l)
{
        if(f.size() > l.size())
        {
                cout << "string :"  << f << " > " << l << endl;
        }
        else
        {
                cout << "string :"  << f << " < " << l << endl;
        }
}

void comp(const char *f,const char *l)
{
        if(strlen(f) > strlen(l))
        {
                cout << "char* :"  << strlen(f) << " > " << strlen(l) << endl;
        }
        else
        {
                cout << "char* :"  << strlen(f) << " < " << strlen(l) << endl;
        }
}

//类模版
template<typename T1,typename T2>
class Argv
{
        public:
                Argv(){};
                Argv(T1 argv1,T2 argv)
                {
                        this->argv1 = argv1;
                        this->argv = argv;
                }

                void print_info()
                {
                        cout << "<T1,T2> argv1 : " << argv1 << "," << "argv :" << argv << endl;
                }

        private:
                T1 argv1;
                T2 argv;
};

//类模版偏特化
template<typename T>
class Argv<T,int>
{
        public:
                Argv(){};
                Argv(T argv1,int argv)
                {
                        this->argv1 = argv1;
                        this->argv = argv;
                }

                void print_info()
                {
                        cout << "<T> argv1 : " << argv1 << "," << "argv :" << argv << endl;
                }

        private:
                T argv1;
                int argv;
};

template<typename T>
class Argv<T *,int>
{
        public:
                Argv(){};
                Argv(T argv1,int argv)
                {
                        this->argv1 = argv1;
                        this->argv = argv;
                }

                void print_info()
                {
                        cout << "<T*> argv1 : " << argv1 << "," << "argv :" << argv << endl;
                }

        private:
                T argv1;
                int argv;
};

template<typename T>
class Argv<T&,int>
{
        public:
                Argv(){};
                Argv(T argv1,int argv)
                {
                        this->argv1 = argv1;
                        this->argv = argv;
                }

                void print_info()
                {
                        cout << "<T&> argv1 : " << argv1 << "," << "argv :" << argv << endl;
                }

        private:
                T argv1;
                int argv;
};

//类模版全特化
template<>
class Argv<string,int>
{
        public:
                Argv(){};
                Argv(string argv1,int argv)
                {
                        this->argv1 = argv1;
                        this->argv = argv;
                }

                void print_info()
                {
                        cout << "<string,int> argv1 : " << argv1 << "," << "argv :" << argv << endl;
                }

        private:
                string argv1;
                int argv;
};

template<typename T>
void copy_t(T* dest,const T* src,const int cnt)
{
        if(is_pod<T>::value)
        {
                cout << "is_pod ";
                memcpy(dest,src,cnt*sizeof(T));
        }
        else
        {
                cout << "is not pod ";
                for(auto i = 0;i < cnt;i++)
                {
                        dest[i] = src[i];
                }
        }
}

void copy_t(string &dest,string &src)
{
        dest = src;
}

//萃取实现is_pod

template<typename T>
class is_pod_t
{
        public:
                static bool value;
};
template<typename T>
bool is_pod_t<T>::value = false;

template<>
class is_pod_t<int>
{
        public:
                static bool value;
};
bool is_pod_t<int>::value = true;

template<>
class is_pod_t<char>
{
        public:
                static bool value;
};
bool is_pod_t<char>::value = true;

template<>
class is_pod_t<float>
{
        public:
                static bool value;
};
bool is_pod_t<float>::value = true;

template<>
class is_pod_t<double>
{
        public:
                static bool value;
};
bool is_pod_t<double>::value = true;

template<>
class is_pod_t<long>
{
        public:
                static bool value;
};
bool is_pod_t<long>::value = true;

template<typename T>
void copy_t1(T* dest,const T* src,const int cnt)
{
        if(is_pod_t<T>::value)
        {
                cout << "is_pod ";
                memcpy(dest,src,cnt*sizeof(T));
        }
        else
        {
                cout << "is not pod ";
                for(auto i = 0;i < cnt;i++)
                {
                        dest[i] = src[i];
                }
        }
}

//萃取实现is_pod
struct Type
{
        typedef int value_type;
};

struct True_type
{
        bool get_type()
        {
                return true;
        }
};

struct False_type
{
        bool get_type()
        {
                return false;
        }
};

template<typename T>
struct is_pod_s
{
        typedef False_type value_type;
};

template<>
struct is_pod_s<int>
{
        typedef True_type value_type;
};

template<>
struct is_pod_s<double>
{
        typedef True_type value_type;
};

template<>
struct is_pod_s<long>
{
        typedef True_type value_type;
};

template<>
struct is_pod_s<float>
{
        typedef True_type value_type;
};

template<>
struct is_pod_s<char>
{
        typedef True_type value_type;
};

template<typename T>
void copy_t2(T* dest,const T* src,const int cnt)
{
        if(is_pod_s<T>::value)
        {
                cout << "is_pod ";
                memcpy(dest,src,cnt*sizeof(T));
        }
        else
        {
                cout << "is not pod ";
                for(auto i = 0;i < cnt;i++)
                {
                        dest[i] = src[i];
                }
        }
}

int main()
{
        string s1 = "linux";
        string s2 = "windows";
        string s3[3] = {"linux","windows","macos"};
        string s4[3];
        string s6[3];
        string s7[3];
        string s5;
        int a = 6;
        int b;
        int c;
        comp(4.8,5.6);
        comp(s1,s2);
        comp("linux","windows");

        Argv<string,int> a1(s1,27);
        Argv<string,string> a2(s1,s2);
        Argv<int,string> a3(27,s2);
        Argv<int&,int> a4(a,27);
        Argv<string&,int> a5(s1,27);
        Argv<int*,int> a6(a,27);
        a1.print_info();
        a2.print_info();
        a3.print_info();
        a4.print_info();
        a5.print_info();
        a6.print_info();

        copy_t(s4,s3,3);
        cout << "s4 :";
        for(auto i = 0;i < 3;i++)
        {
                cout << s4[i] << " ";
        }
        cout << endl;
        copy_t(s5,s1);
        cout << "s1:" << s1 << " s5: " << s5 << endl;

        copy_t1(s6,s3,3);
        cout << "s6 :";
        for(auto i = 0;i < 3;i++)
        {
                cout << s6[i] << " ";
        }
        cout << endl;
        copy_t1(&b,&a,1);
        cout << "a:" << a << " b: " << b << endl;
        copy_t1(s7,s3,3);
        cout << "s6 :";
        for(auto i = 0;i < 3;i++)
        {
                cout << s7[i] << " ";
        }
        cout << endl;
        copy_t1(&c,&a,1);
        cout << "a:" << a << " c: " << c << endl;

        return 0;
}

执行结果:

demo6:

        智能指针

目录:

run.sh

#!/bin/bash

if [ -f ./Makefile ]
then
        make clean
fi

cmake .

make

echo "---------------------------------"

./pro

clean.sh

#!/bin/bash

rm -rf CMakeFiles pro Makefile CMakeCache.txt cmake_install.cmake

check_mem.sh

valgrind --tool=memcheck --leak-check=full --show-reachable=yes --trace-children=yes -s ./pro

CMakeLists.txt

CMAKE_MINIMUM_REQUIRED(VERSION 2.20)                            #最低版本要求

SET(CMAKE_CXX_COMPILER "g++-11")                                #设置g++编译器

set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g")                    #添加编译选项

PROJECT(CLASS)                                                  #设置工程名

MESSAGE(STATUS "string test")                                   #打印消息

ADD_EXECUTABLE(pro main.cpp)                                    #生成可执行文件

main.cpp

#include <iostream>
#include <memory>
#include <cstring>

using namespace std;

template<typename T,int SIZE>
class  Test
{
        private:
        public:
                T *num;
                Test(){};
                Test(int size)
                {
                        cout << "user con" << endl;
                        num = new T[SIZE]; 
                        if(num != NULL)
                        {
                                for(auto i = 0;i < SIZE;i++)
                                        num[i] = size;
                        }
                };

                ~Test()
                {
                        cout << "user descon" << endl;
                        if(num != NULL)
                                delete[] num;
                };

                void print()
                {
                        for(auto i = 0;i < SIZE;i++)
                                cout << num[i] << " " ;
                        cout << endl;
                }
};

template<typename T,int SIZE>
void set_t(T *t)
{
        for(auto i = 0;i < SIZE;i++)
                t[i] = i;
}

template<typename T,int SIZE>
void get_t(T *t)
{
        for(auto i = 0;i < SIZE;i++)
                cout <<  t[i] << " ";
        cout << endl;
}

class front;
class back;

class front
{
        public:
                //shared_ptr<back> bptr;
                weak_ptr<back> bptr;
                front(){};
                front(int num)
                {
                        cout << "front" << endl;
                };
                ~front()
                {
                        cout << "~front()" << endl;
                }
};

class back
{
        public:
                //shared_ptr<front> fptr;
                weak_ptr<front> fptr;
                back(){};
                back(int num)
                {
                        cout << "back" << endl;
                };
                ~back()
                {
                        cout << "~bak()" << endl;
                }
};

int main()
{
        unique_ptr<Test<int,3>> up1(new Test<int,3>(3));
        cout << "up1 :";
        up1->print();
        //移动构造时会将前对象的所有权转移给当前对象
        unique_ptr<Test<int,3>> up2(move(up1));
        cout << "up2 :";
        up2->print();
        unique_ptr<Test<int,3>> up3 = unique_ptr<Test<int,3>>(new Test<int,3>(3));
        cout << "up3 :";
        up3->print();

        using deleter =  void(*)(int*); //定义删除器类型别名
        unique_ptr<int[],deleter> up4(new int[3],[](int *p){delete [] p;});
        set_t<int,3>(up4.get());
        cout << "up4 :";
        get_t<int,3>(up4.get());

        //重新绑定对象前会调用前对象的删除器删除前对象
        up4.reset(new int[4]);
        set_t<int,4>(up4.get());
        cout << "up4 :";
        get_t<int,3>(up4.get());

        unique_ptr<int[],deleter> up5(new int[5],[](int *p){delete [] p;});
        set_t<int,5>(up5.get());
        cout << "up5 :" ;
        get_t<int,5>(up5.get());
        up4.swap(up5);
        cout << "up4 :";
        get_t<int,3>(up4.get());
        cout << "up5 :" ;
        get_t<int,5>(up5.get());

        //释放权限后要手动释放内存
        int *p6 = up4.release();
        delete p6;
        int *p7 = up5.release();
        delete p7;

        //拷贝构造会增加管理对象,移动构造不会
        shared_ptr<Test<int,3>> sp1(new Test<int,3>(3));
        cout << "sp1 :";
        sp1->print();
        shared_ptr<Test<int,3>> sp2(sp1);
        cout << "sp2 :";
        sp2->print();
        shared_ptr<Test<int,3>> sp3 = sp1;
        cout << "sp3 :";
        sp3->print();
        shared_ptr<Test<int,3>> sp4(move(sp1));
        cout << "sp4 :";
        sp4->print();
        cout << "sp1 use_count :" << sp1.use_count() << endl;
        cout << "sp2 use_count :" << sp2.use_count() << endl;
        cout << "sp3 use_count :" << sp3.use_count() << endl;
        cout << "sp4 use_count :" << sp4.use_count() << endl;

        weak_ptr<Test<int,6>> wp;
        {
                auto sp5 = make_shared<Test<int,6>>(6);
                cout << "sp5 :";
                sp5->print();
                if(sp5.unique())
                cout << "sp5 use_count = 1" << endl;
                if(!wp.lock())
                        wp = sp5;
                if(wp.expired())
                        cout << "sp5 deleted 1" << endl;
                wp.reset();
                cout << "wp.use_count :" << wp.use_count() << endl;
                if(wp.expired())
                        cout << "sp5 deleted 2" << endl;
        }
        if(wp.expired())
                cout << "sp5 deleted 3" << endl;

        shared_ptr<front> f(new front(1));
        shared_ptr<back>  b(new back(1));
        cout << "f.use_count :" << f.use_count() << endl;
        cout << "b.use_count :" << b.use_count() << endl;
        f->bptr = b;
        b->fptr = f;
        cout << "f.use_count :" << f.use_count() << endl;
        cout << "b.use_count :" << b.use_count() << endl;

        return 0;
}

结果示例:

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

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

相关文章

个人做量化交易一定不靠谱?

在某乎上的『量化』话题下&#xff0c;有一类关于个人量化交易者的问题很热门&#xff0c;比如『个人做量化交易靠不靠谱吗&#xff1f;』、『个人做量化交易到底可不可行&#xff1f;』、『个人做量化没啥优势&#xff0c;不如买量化基金&#xff1f;』。 关注度高的&#xff…

2025年穿戴甲全球市场预测与分析

传统美甲一直是大美业里的为数不多的“稳定”型项目&#xff0c;无论是产品、技术还是市场规模。直到2020年开始&#xff0c;穿戴甲的出现&#xff0c;打破了这一平衡生态&#xff0c;究其原因还是因为&#xff1a;创新&#xff01;通常我们在判断一个创新型产品或者服务的出现…

远程访问mysql数据库的正确打开方式

为了安全&#xff0c;mysql数据库默认只能本机登录&#xff0c;但是在有些时候&#xff0c;我们会有远程登录mysql数据库的需求&#xff0c;这时候应该怎么办呢&#xff1f; 远程访问mysql数据&#xff0c;需要两个条件&#xff1a; 首先需要mysql服务器将服务绑定到0.0.0.0…

LazyLLM:长上下文场景下提高LLM推理效率

LazyLLM旨在优化大型语言模型&#xff08;LLM&#xff09;在处理长文本语境下的推理效率。传统上&#xff0c;LLM的推理过程分为预填充和解码两个阶段&#xff0c;其中预填充阶段负责计算并存储输入提示的所有token的键值&#xff08;KV&#xff09;缓存&#xff0c;这一步骤在…

转转上门履约服务拆分库表迁移实践

文章目录 1 背景2 数据迁移方案2.1 方案一&#xff1a;双写新旧库2.2 方案二&#xff1a;灰度开关切换新旧库 3 迁移细节3.1 业务代码改造3.2 数据同步3.3 数据一致性校验 4 总结5 参考资料 1 背景 随着业务不断发展&#xff0c;一个服务中部分功能模块适合沉淀下来作为通用的…

OverlayFS 文件系统介绍

引言 OverlayFS&#xff08;Overlay Filesystem&#xff09;是 Linux 内核中的一种联合文件系统&#xff08;Union Filesystem&#xff09;&#xff0c;它通过叠加多个目录形成一个单一的文件系统视图。作为 Docker 的默认存储驱动之一&#xff0c;OverlayFS 在提高性能和简化容…

Python 装饰器简单使用

在Python编程中&#xff0c;装饰器&#xff08;Decorators&#xff09;是一种强大且优雅的功能&#xff0c;它允许我们在不修改原有函数代码的情况下&#xff0c;给函数增加新的功能。装饰器本质上是一个函数&#xff0c;它接收一个函数作为参数并返回一个新的函数&#xff0c;…

【医疗大数据】健康分析法应用于商业领域的文献回顾

这几天在看医疗大数据的文章&#xff0c;找到了这篇关于健康分析学在商业领域的应用&#xff0c;概括性地探讨了通过医疗大数据来解决医疗领域的问题。 Health analytics in business research: a literature review 1、研究背景&#xff1a; 本文探讨了健康分析学&#xff0…

吴恩达老师机器学习-ex3

使用逻辑回归 导入库&#xff0c;因为这次的数据是mat文件&#xff0c;需要使用scipy库中的loadmat进行读取数据。 通过对数据类型的分析&#xff0c;发现是字典类型&#xff0c;查看该字典的键&#xff0c;可以发现又X&#xff0c;y等关键字。 import numpy as np import m…

Python none和0区别是什么

None是Python中的一个关键字&#xff0c;None本身也是个一个数据类型&#xff0c;而这个数据类型就是None&#xff0c;它和0、空字符串以及false均不一样&#xff0c;这些都只是对象&#xff0c;而None也是一个类。 给个bool测试&#xff1a; val None if val:print "No…

【应急响应】Linux权限维持 -隐藏权限

前言 不知攻焉知守&#xff0c;学会排查就要先学习如何攻击。 隐藏文件 Linux下创建一个隐藏文件&#xff1a;touch .test.txt 查看Linux下的隐藏文件需要用到命令&#xff1a;ls -al 隐藏文件时间戳 touch -r .docker hello.php 创建的hello.php文件会和.docker创建文件的时间…

printf颜色格式化使用

前言 本文介绍了如何使用C语言标准函数进行字符的有色打印&#xff0c;以及实现一些特殊的输出。 一、一般使用 在C语言中&#xff0c;printf常用来进行标准化格式输出&#xff0c;其作用是将字符串打印到屏幕上面&#xff0c;其中可以使用占位符、转义符来对字符串进行格式…

[玄机]流量特征分析-常见攻击事件 tomcat

题目网址【玄机】&#xff1a;https://xj.edisec.net/ Tomcat是一个开源的Java Servlet容器&#xff0c;它实现了Java Servlet和JavaServer Pages (JSP) 技术&#xff0c;提供了一个运行这些应用程序的Web服务器环境。Tomcat由Apache软件基金会的Jakarta项目开发&#xff0c;是…

使用思科模拟电子邮件实验

实验十 电子邮件实验 文章目录 实验十 电子邮件实验1.实验目的2.实验流程3.实验步骤 1.实验目的 1&#xff09;理解电子邮件的含义 2&#xff09;理解邮件系统的工作过程 3&#xff09;掌握简单的邮件服务器的配置 2.实验流程 开始 → 布置拓扑 → 配置路由及IP地址 → 配置…

JAVA—面向对象编程基础

面向对象是java编程的套路。更符合人类思维习惯&#xff0c;编程更直观。面向对象有三大特征&#xff1a;封装&#xff0c;继承&#xff0c;多态。 目录 1.理解面向对象 2.对象在计算机中的执行原理 3.类和对象的一些注意事项 4.类与对象的一些语法知识 &#xff08;1&am…

小阿轩yx- KVM 高级功能部署

小阿轩yx- KVM 高级功能部署 案例分析 案例概述 企业内部为了使服务器资源达到最大化利用会进行 KVM 虚拟化每台服务器部署多台 KVM 虚拟机。KVM 虚拟机数量不断增多个别服务器会出现资源过载现象&#xff0c;就需要对部分 KVM 虚拟机迁移针对可停机的 KVM 虚拟机可使用静态…

为你的世界,开一扇任意门 (中篇)

传送门 《为你的世界&#xff0c;开一扇任意门&#xff08;上篇&#xff09;》 一、蓬门今始为君开 在上篇&#xff0c;为各位朋友展示了&#xff0c;在【我的电脑】中添加自己的任意门后的效果。 本篇直接上干货&#xff0c;手把手教大家实操&#xff08;dll插件和自动化注册…

PostgreSQL如何入门学习?

在各种数据岗招聘中&#xff0c;SQL几乎成为了必备技能。有公司的地方就会有数据&#xff0c;有数据的地方就会有数据库&#xff0c;有数据库的地方就会有SQL。 SQL在数据分析中到底有多重要&#xff1f;这么说吧&#xff0c;除了Excel外&#xff0c;SQL是数据工作最常接触的到…

Java--接口和内部类

目录 接口接口的使用接口的特性多继承问题对象类型进行比较深拷贝和浅拷贝浅拷贝深拷贝 接口和抽象类区别 Object类内部类实例内部类静态内部类局部内部类匿名内部类 接口 接口是一种引用数据类型&#xff0c;语法和抽象类类似&#xff0c;只不过需要把abstract换成interface 接…

JavaScript (七)——JavaScript 对象和函数

目录 JavaScript 对象 真实生活中的对象&#xff0c;属性和方法 JavaScript 对象 对象定义 对象属性 访问对象属性 对象方法 JavaScript 函数 JavaScript 函数语法 调用带参数的函数 带有返回值的函数 局部 JavaScript 变量 全局 JavaScript 变量 JavaScript 变量…