C++ primer plus--string 类和标准模板库

16 string 类和标准模板库

16.1 string 类
16.2 智能指针模板类

(1)智能指针是行为类似于指针的类对象,可以帮助管理动态内存分配。可避免:

1)有些内存资源已经被释放,但指向它的指针并没有改变指向(成为了野指针),并且后续还在使用;

2)重复释放同一块内存资源;

3)忘记释放内存,造成内存泄露。

当智能指针过期时,其析构函数将自动调用 delete 释放内存。

(2)智能指针的使用

智能指针包含在头文件 中,有三种 shared_ptr、auto_ptr、unique_ptr、weak_ptr。

1)shared_ptr 智能指针 (强引用)

shared_ptr 实现共享式拥有概念,即多个 shared_ptr 智能指针可以共同指向同一块堆内存。该指针在实现上采用的的是引用计数机制,当某一个指针放弃了该内存的使用权,计数减 1,直至为 0 时,内存释放。

参考:http://c.biancheng.net/view/7898.html

2)auto_ptr 智能指针(C++98 的⽅案,C ++ 11 已抛弃)

auto_ptr 采⽤所有权模式,

auto_ptr p1 (new string ("hello"));
auto_ptr p2;
p2 = p1; //auto_ptr 不会报错.

此时不会报错,p2 接管了 p1 的所有权,但是当程序运⾏时访问 p1 将会报错。所以 auto_ptr 的缺点是:存在潜
在的内存崩溃问题!

3)unique_ptr 智能指针(替代 auto_ptr)

unique_ptr 实现独占式拥有或严格拥有概念。保证同一时间内只有一个智能指针可以指向该对象,可避免资源泄露。

例如

unique_ptr p1 (new string ("auto"));   
unique_ptr p2;                       
p2 = p1;  //此时会报错!不可剥夺所有权

3)weak_ptr 智能指针(弱引用)
weak_ptr 是为了配合 shared_ptr 而引入的一种智能指针,它不具有普通指针的行为。可以通过 weak_ptr 获取 shared_ptr 的状态信息,例如:有多少指向相同的 shared_ptr 指针、shared_ptr 指针指向的堆内存是否已经被释放等等。

需要注意的是,当 weak_ptr 类型指针的指向和某一 shared_ptr 指针相同时,weak_ptr 指针并不会使所指堆内存的引用计数加 1;同样,当 weak_ptr 指针被释放时,之前所指堆内存的引用计数也不会因此而减 1。也就是说,weak_ptr 类型指针并不会影响所指堆内存空间的引用计数。

示例:

#include 
#include 
using namespace std;
int main()
{
    std::shared_ptr sp1(new int(10));
    std::shared_ptr sp2(sp1);
    std::weak_ptr wp(sp2);   //三者指向同一块内存
    
    cout << wp.use_count() << endl;     //输出和 wp 同指向的 shared_ptr 类型指针的数量

    sp2.reset();    //释放 sp2
    cout << wp.use_count() << endl;
    
    cout << *(wp.lock()) << endl;
        //借助 lock() 函数,返回一个和 wp 同指向的 shared_ptr 类型指针,获取其存储的数据
    return 0;
}

输出

2
1
10
16.3 标准模板库

(1)模板类 vector

  • 迭代器

  • STL 函数:for_each、sort()等

(2)基于范围的 for 循环(C++11)

double prices[5] = {1.2, 3.4, 4, 3.1, 1,1}
for (auto x: prices)
    cout << x << endl;
16.4 泛型编程

STL 是一种泛型编程。面向对象编程关注的是数据,而泛型编程关注的是算法,旨在使用同一个函数处理不同类型的容器。他们之间的共同点是抽象和创建可重用代码。

(1)迭代器

遍历数组元素

for (vector::iterator pr=v.begin(); pr!=v.end(); pr++)
    cout << *pr <

或者 C++11 方法

for(auto x: v)
    cout<< x <

(2)五种迭代器

  • 输入迭代器

  • 输出迭代器

  • 正向迭代器

  • 双向迭代器

  • 随机访问迭代器

(3)容器种类

参考:https://blog.csdn.net/wangxiaolong_china/article/details/8362540

1)顺序容器

  • vector:最简单的序列类型,使用最多,支持数组表示法和随机访问。在尾部添加和删除元素的时间是固定的,但在头部或中间插入和删除元素的复杂度为线性时间。

  • deque:双端队列(double-ended queue)。可在队首或队尾添加或删除元素,时间是固定的。

  • list:双向链表。在链表任意位置插入或删除元素的时间都是固定的(相当于只需要操作指针指向)。不支持数组表示法和随机访问。

vector 强调的是通过随机访问进行快速访问,而 list 强调的是快速插入和删除。

2)关联容器

关联容器将值与键关联在一起,并使用键来查找值。它的优点在于提供了对元素的快速访问。关联元素允许插入新元素,但不能指定元素的位置。

其中,set 和 multiset 比较特殊,只有键没有值,值就是键。类似 list,但不支持随机访问(按索引访问),会默认从小到大自动排序。set 不允许重复元素,multiset 允许重复元素。

map 与 multimap是存储 key-value(键-值-对)类型的容器。map 只允许 key 与 value 一一对应;multimap一个key可对应多个value。

添加元素时,使用 pair 或 make_pair 使 key 和 value 结合成一个元素(类似结构体),然后再插入。

std::pair pair1(1, 1.1);
std::pair pair2 = std::make_pair(1, 1.1);

std::map map1;
map1.insert(pair1);      //插入
map1.insert(pair2);

//遍历输出
for(std::map::iterator it=map1.begin(); it!=map1.end(); it++)
{  
    std::cout << "First Member:  " << it->first << std::endl;  
    std::cout << "Second Member: " << it->second << std::endl;  
} 

3)容器适配器

  • queue:限制比 deque 多,不可随机访问队列元素,也不可遍历队列。常用操作:队尾添加、队首删除。(FIFO)

  • priority_queue:优先队列。操作和普通队列一致,但元素会默认降序排列。

  • stack:限制比 vector 多,不可随机访问栈元素,也不可遍历栈。常用操作:栈顶添加、栈顶删除。(LIFO)

16.5 函数对象

C++11 提供了函数指针和函数符的替代品 — Lambda表达式。

16.6 算法

(1)STL 将算法库分为四类:

  • 非修改式序列操作:如查找、遍历

  • 修改式序列操作

  • 排序和相关操作

  • 通用数字运算

也可以分类为就地算法(在原存储位置进行操作,如 sort ( ) )和复制算法(将结果存放在另一个存储位置,如 copy() )。

16.7 其他库

你可能感兴趣的:(C++,c++)