STL(模板学习)day03 模板特性 容器、迭代器和泛型算法 标准模板库(STL)

四、模板特性

7.编译模型

导出模型:通过export关键字,将模板声明为导出,这样编译器在对模板进行一次编译时会将该模板内部表示,缓存在.o文件中,等到链接阶段,在结合实例化该模板的具体类型,补充做二次编译,得到相应的具体函数和具体类,最后完成二进制代码的链接。但是,很遗憾,目前阶段大部分C++编译器都不支持这种做法。因此,多数情况下依然采用包含模型或者预实例化模型,解决模板的分离编译问题。
代码:exp/
cmp.h

// 声明
export template<typename T>
T const& min(T const& x, T const& y);
export template<typename T>
T const& max(T const& x, T const& y);
export template<typename T>
class Comparator {
public:
    Comparator(T const& x, T const& y);
    T const& min(void) const;
    T const& max(void) const;
private:
    T const& m_x;
    T const& m_y;
};

cmp.cpp

// 实现
#include "cmp.h"
template<typename T>
T const& min(T const& x, T const& y) {
    return x < y ? x : y;
}
template<typename T>
T const& max(T const& x, T const& y) {
    return x < y ? y : x;
}
template<typename T>
Comparator<T>::Comparator(T const& x,
    T const& y) : m_x(x), m_y(y) {}
template<typename T>
T const& Comparator<T>::min(void) const {
    return m_x < m_y ? m_x : m_y;
}
template<typename T>
T const& Comparator<T>::max(void) const {
    return m_x < m_y ? m_y : m_x;
}

use.cpp

// 使用
#include <iostream>
using namespace std;
#include "cmp.h"
int main(void) {
    int a = 123, b = 456;
    double c = 1.23, d = 4.56;
    string e = "world", f = "hello";
    cout << ::min(a, b) << ' '
        << ::max(a, b) << endl;
    cout << ::min(c, d) << ' '
        << ::max(c, d) << endl;
    cout << ::min(e, f) << ' '
        << ::max(e, f) << endl;
    Comparator<int> ci(a, b);
    cout << ci.min() << ' '
        << ci.max() << endl;
    Comparator<double> cd(c, d);
    cout << cd.min() << ' '
        << cd.max() << endl;
    Comparator<string> cs(e, f);
    cout << cs.min() << ' '
        << cs.max() << endl;
    return 0;
}

8.预编译头文件
提升编译速度的技巧。
将一些公用头文件,或者是包含大量与模板实现有关的代码,放到一个独立的.h文件中,将该.h文件单独编译为一个.gch文件,即预编译头文件。编译任何包含此独立头文件的cpp文件时,都不再编译头文件,而是直接从.gch文件中读取内容,以此减少对相同代码重复编译的次数,提升编译速度,缩短编译时间。
代码:hello.h、hello.cpp
注意,一旦修改了与预编译头文件有关的文件内容,一定要重新编译生成预编译头文件,以反映所作出的改变。
五、容器、迭代器和泛型算法
容器:双向线性链表容器
迭代器:正向可写迭代器
泛型算法:线性查找算法
代码:list.cpp

#include <cstring>
#include <iostream>
#include <stdexcept>
using namespace std;
// 双向线性链表容器
template<typename T>
class List {
public:
    // 构造器、析构器、拷贝构造器、
    // 拷贝赋值运算符
    List(void) : m_head(NULL), m_tail(NULL) {}
    ~List(void) {
        clear();
    }
    List(List const& that) : m_head(NULL),
        m_tail(NULL) {
        for (Node* node = that.m_head;
            node; node = node->m_next)
            push_back(node->m_data);
    }
    List& operator=(List const& that) {
        if (&that != this) {
            List list(that);
            swap(m_head, list.m_head);
            swap(m_tail, list.m_tail);
        }
        return *this;
    }
    // 获取首元素
    T& front(void) {
        if (empty())
            throw underflow_error(
                "链表下溢!");
        return m_head->m_data;
    }
    T const& front(void) const {
        return const_cast<List&>(
            *this).front();
    }
    // 向首部压入
    void push_front(T const& data) {
        m_head = new Node(data, NULL, m_head);
        if (m_head->m_next)
            m_head->m_next->m_prev = m_head;
        else
            m_tail = m_head;
    }
    // 从首部弹出
    void pop_front(void) {
        if (empty())
            throw underflow_error(
                "链表下溢!");
        Node* next = m_head->m_next;
        delete m_head;
        m_head = next;
        if (m_head)
            m_head->m_prev = NULL;
        else
            m_tail = NULL;
    }
    // 获取尾元素
    T& back(void) {
        if (empty())
            throw underflow_error(
                "链表下溢!");
        return m_tail->m_data;
    }
    T const& back(void) const {
        return const_cast<List&>(
            *this).back();
    }
    // 向尾部压入
    void push_back(T const& data) {
        m_tail = new Node(data, m_tail);
        if (m_tail->m_prev)
            m_tail->m_prev->m_next = m_tail;
        else
            m_head = m_tail;
    }
    // 从尾部弹出
    void pop_back(void) {
        if (empty())
            throw underflow_error(
                "链表下溢!");
        Node* prev = m_tail->m_prev;
        delete m_tail;
        m_tail = prev;
        if (m_tail)
            m_tail->m_next = NULL;
        else
            m_head = NULL;
    }
    // 删除所有匹配元素
    void remove(T const& data) {
        for (Node* node = m_head, *next; node;
            node = next) {
            next = node->m_next;
            if (node->m_data == data) {
                if (node->m_prev)
                    node->m_prev->m_next =
                        node->m_next;
                else
                    m_head = node->m_next;
                if (node->m_next)
                    node->m_next->m_prev =
                        node->m_prev;
                else
                    m_tail = node->m_prev;
                delete node;
            }
        }
    }
    // 清空
    void clear(void) {
        for (Node* next; m_head;
            m_head = next) {
            next = m_head->m_next;
            delete m_head;
        }
        m_tail = NULL;
    }
    // 判空
    bool empty(void) const {
        return m_head == NULL &&
            m_tail == NULL;
    }
    // 大小
    size_t size(void) const {
        size_t nodes = 0;
        for (Node* node = m_head; node;
            node = node->m_next)
            ++nodes;
        return nodes;
    }
    // 插入流
    friend ostream& operator<<(ostream& os,
        List const& list) {
        for (Node* node = list.m_head; node;
            node = node->m_next)
            os << *node;
        return os;
    }
private:
    // 节点
    class Node {
    public:
        // 构造器
        Node(T const& data, Node* prev = NULL,
            Node* next = NULL) : m_data(data),
            m_prev(prev), m_next(next) {}
        // 插入流
        friend ostream& operator<<(
            ostream& os, Node const& node) {
            return os << '(' << node.m_data
                << ')';
        }
        T     m_data; // 数据
        Node* m_prev; // 前指针
        Node* m_next; // 后指针
    };
    Node* m_head; // 头指针
    Node* m_tail; // 尾指针
};
// 测试用例
void test1 (void) {
    List<int> list;
    cout << list << endl; // 空
    list.push_front(30);
    list.push_front(20);
    list.push_front(10);
    cout << list << endl; // 10 20 30
    --list.front();
    cout << list << endl; // 9 20 30
    List<int> const& cr = list;
    cout << cr.front() << endl; // 9
    //cr.front()++;
    list.pop_front();
    cout << list << endl; // 20 30
    list.push_back(40);
    list.push_back(50);
    list.push_back(60);
    cout << list << endl; // 20 30 40 50 60
    list.back()++;
    cout << list << endl; // 20 30 40 50 61
    List<int> const* cp = &list;
    cout << cp->back() << endl; // 61
    //--cp->back();
    list.pop_back();
    cout << list << endl; // 20 30 40 50
}
void test2(void) {
    List<int> l1;
    l1.push_back(10);
    l1.push_back(20);
    l1.push_back(30);
    List<int> l2 = l1; // 拷贝构造
    cout << "l1: " << l1 << endl;
    cout << "l2: " << l2 << endl;
    ++l1.front();
    ++l2.back();
    cout << "l1: " << l1 << endl;
    cout << "l2: " << l2 << endl;
    l1 = l2; // 拷贝赋值
    cout << "l1: " << l1 << endl;
    cout << "l2: " << l2 << endl;
    ++l1.front();
    ++l2.back();
    cout << "l1: " << l1 << endl;
    cout << "l2: " << l2 << endl;
}
void test3(void) {
    int a[] = {10, 20, 30, 20, 40,
        20, 50, 20, 20, 60};
    List<int> list;
    for (size_t i = 0; i < sizeof(a) /
        sizeof(a[0]); ++i)
        list.push_back(a[i]);
    cout << list << endl;
    list.remove(20);
    cout << list << endl;
}
int main(void) {
    //test1();
    //test2();
    test3();
    return 0;
}

六、标准模板库(STL)
1.主要内容
1)容器
A.线性容器:向量(vector)、双端队列(deque)、列表(list)
B.适配器容器:堆栈(stack)、队列(queue)、优先队列(priority_queue)
C.关联容器:映射(map)、多重映射(multimap)、集合(set)、多重集合(multiset)
2)迭代器:
A.成员迭代器:正向和反向、可写和只读、随机和顺序
B.全局迭代器:插入迭代器、IO流迭代器
3)泛型算法
查找、排序、拆分、合并、交换、遍历,等等
2.向量(vector)
1)基本特性和实例化
向量中的元素被存储在一段连续的内存空间中,通过下标随机访问向量中的元素,其效率等价于数组。
向量的内存空间会随着新元素的加入而自动增长。
内存空间的连续性不会妨碍向量元素的持续增加。
在创建向量的时候,也可以提前预分配内存空间,只要这些空间够用就不再分配新的内存空间,除非使用用发现不够用了,再自动扩充内存。
#include
vector<元素类型> 向量对象;
vector vi;
空向量,占内存。
vector<元素类型> 向量对象(初始大小);
vector vi(5); // 0 0 0 0 0
vector<元素类型> 向量对象(初始大小, 初值);
vector vi(5, 10); // 10 10 10 10 10
vector<元素类型> 向量对象(起始迭代器, 终止迭代器);
凡是用起始迭代器和终止迭代器表示容器中的元素范围,终止迭代器时范围中最后一个元素的下一个位置的迭代器:
[起始迭代器, 终止迭代器)
1 2 3 4 5 6 7
^ ^
| |
起始 终止 -> 2 3 4 5
代码:vec1.cpp

#include <iostream>
#include <vector>
using namespace std;
void print(vector<int> const& vec) {
    cout << "容量:"
        << vec.capacity() << endl;
    cout << "大小:"
        << vec.size() << endl;
    cout << "字节:"
        << sizeof(vec) << endl;
    cout << "元素:";
    for (size_t i = 0; i < vec.size(); ++i)
        cout << vec[i] << ' ';
    cout << endl;
}
int main(void) {
    vector<int> v1;
    print(v1);
    vector<int> v2(5);
    print(v2);
    vector<int> v3(5, 10);
    print(v3);
    v3.push_back(20);
    print(v3);
    int a[] = {1, 2, 3, 4, 5, 6, 7};
    vector<int> v4(&a[2], &a[5]);
    print(v4);
    vector<int> v5(&a[0], &a[7]);
    print(v5);
    return 0;
}

2)迭代器
连续内存的容器->随机迭代器->处理顺序迭代器提供的功能以外还支持与整数的加减法运算,以及同类型迭代器之间的大小比较和减法运算。
iterator: 正向可写迭代器
const_iterator: 正向只读迭代器
reverse_iterator: 反向可写迭代器
const_reverse_iterator: 反向只读迭代器

以下是对提供的参考资料的总结,按照要求结构化多个要点分条输出: 4G/5G无线网络优化与网规案例分析: NSA站点下终端掉4G问题:部分用户反馈NSA终端频繁掉4G,主要因终端主动发起SCGfail导致。分析显示,在信号较好的环境下,终端可能因节能、过热保护等原因主动释放连接。解决方案建议终端侧进行分析处理,尝试关闭节电开关等。 RSSI算法识别天馈遮挡:通过计算RSSI平均值及差值识别天馈遮挡,差值大于3dB则认定有遮挡。不同设备分组规则不同,如64T和32T。此方法可有效帮助现场人员识别因环境变化引起的网络问题。 5G 160M组网小区CA不生效:某5G站点开启100M+60M CA功能后,测试发现UE无法正常使用CA功能。问题原因在于CA频点集标识配置错误,修正后测试正常。 5G网络优化与策略: CCE映射方式优化:针对诺基亚站点覆盖农村区域,通过优化CCE资源映射方式(交织、非交织),提升RRC连接建立成功率和无线接通率。非交织方式相比交织方式有显著提升。 5G AAU两扇区组网:与三扇区组网相比,AAU两扇区组网在RSRP、SINR、下载速率和上传速率上表现不同,需根据具体场景选择适合的组网方式。 5G语音解决方案:包括沿用4G语音解决方案、EPS Fallback方案和VoNR方案。不同方案适用于不同的5G组网策略,如NSA和SA,并影响语音连续性和网络覆盖。 4G网络优化与资源利用: 4G室分设备利旧:面对4G网络投资压减与资源需求矛盾,提出利旧多维度调优策略,包括资源整合、统筹调配既有资源,以满足新增需求和提质增效。 宏站RRU设备1托N射灯:针对5G深度覆盖需求,研究使用宏站AAU结合1托N射灯方案,快速便捷地开通5G站点,提升深度覆盖能力。 基站与流程管理: 爱立信LTE基站邻区添加流程:未提供具体内容,但通常涉及邻区规划、参数配置、测试验证等步骤,以确保基站间顺畅切换和覆盖连续性。 网络规划与策略: 新高铁跨海大桥覆盖方案试点:虽未提供详细内容,但可推测涉及高铁跨海大桥区域的4G/5G网络覆盖规划,需考虑信号穿透、移动性管理、网络容量等因素。 总结: 提供的参考资料涵盖了4G/5G无线网络优化、网规案例分析、网络优化策略、资源利用、基站管理等多个方面。 通过具体案例分析,展示了无线网络优化中的常见问题及解决方案,如NSA终端掉4G、RSSI识别天馈遮挡、CA不生效等。 强调了5G网络优化与策略的重要性,包括CCE映射方式优化、5G语音解决方案、AAU扇区组网选择等。 提出了4G网络优化与资源利用的策略,如室分设备利旧、宏站RRU设备1托N射灯等。 基站与流程管理方面,提到了爱立信LTE基站邻区添加流程,但未给出具体细节。 新高铁跨海大桥覆盖方案试点展示了特殊场景下的网络规划需求。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值