容器库(5)-std::list

std::forward_list是可以从任何位置快速插入和移除元素的容器,不支持快速随机访问,支持正向和反向的迭代。

本文章的代码库:

https://gitee.com/gamestorm577/CppStd

成员函数

构造、析构和赋值

构造函数

可以用元素、元素列表、迭代器或者另一个list来构造list。代码示例:

cpp 复制代码
auto print_func = [](const std::list<float>& list)
{
    for (auto i : list)
    {
        std::cout << i << " ";
    }
    std::cout << std::endl;
};

std::vector<float> vec{1.1f, 2.1f, 3.1f};
std::list<float> l1(5, 1.1f);
std::list<float> l2(5);
std::list<float> l3(vec.begin(), vec.end());
std::list<float> l4(l1);
std::list<float> tmp(l1);
std::list<float> l5(std::move(tmp));
std::list<float> l6{11.1f, 12.1, 13.1f};

print_func(l1);
print_func(l2);
print_func(l3);
print_func(l4);
print_func(l5);
print_func(l6);

输出结果:

bash 复制代码
1.1 1.1 1.1 1.1 1.1 
0 0 0 0 0 
1.1 2.1 3.1 
1.1 1.1 1.1 1.1 1.1 
1.1 1.1 1.1 1.1 1.1 
11.1 12.1 13.1 

析构函数

list析构时,会按照正向顺序依次删除元素。代码示例:

cpp 复制代码
struct MyStruct
{
    MyStruct(int i)
        : Index(i)
    {
    }

    ~MyStruct()
    {
        std::cout << "destruct, Index = " << Index << std::endl;
    }

    int Index = 0;
};

std::list<MyStruct> l;
l.emplace_front(1);
l.emplace_front(3);
l.emplace_front(5);

输出结果:

bash 复制代码
destruct, Index = 5
destruct, Index = 3
destruct, Index = 1

赋值函数

可以用元素列表或者另一个list赋值给forward_list。代码示例:

cpp 复制代码
auto print_func = [](const std::list<float>& list)
{
    for (auto i : list)
    {
        std::cout << i << " ";
    }
    std::cout << std::endl;
};

std::list<float> tmp = {1.1f, 2.1f, 3.1f};
std::list<float> l1;
std::list<float> l2;

l1 = tmp;
l2 = {2.1f, 2.2f, 2.3f, 2.4f};
print_func(l1);
print_func(l2);

输出结果:

bash 复制代码
1.1 2.1 3.1 
2.1 2.2 2.3 2.4 

assign

将值赋值给forward_list,可以是元素、元素列表或者迭代器。代码示例:

cpp 复制代码
auto print_func = [](const std::list<float>& list)
{
    for (auto i : list)
    {
        std::cout << i << " ";
    }
    std::cout << std::endl;
};

std::vector<float> vec(10, 1.2f);
std::list<float> l;

l.assign(5, 1.2);
print_func(l);
l.assign(vec.begin(), vec.end());
print_func(l);
l.assign({1.1f, 2.1f, 3.1f});
print_func(l);

输出结果:

bash 复制代码
1.2 1.2 1.2 1.2 1.2 
1.2 1.2 1.2 1.2 1.2 1.2 1.2 1.2 1.2 1.2 
1.1 2.1 3.1 

元素访问

front

返回首个元素的引用。示例代码:

cpp 复制代码
std::list<float> l = {1.f, 2.f, 3.f};
l.front() = 4.1f;
std::cout << "l front is: " << l.front() << std::endl;

输出结果:

bash 复制代码
l front is: 4.1

back

返回最后一个元素的引用。示例代码:

cpp 复制代码
std::list<float> l = {1.f, 2.f, 3.f};
l.back() = 24.1f;
std::cout << "l back is: " << l.back() << std::endl;

输出结果:

bash 复制代码
l back is: 24.1

迭代器

接口begin、cbegin指向list起始的迭代器,end、cend指向末尾的迭代器。rbegin、crbegin指向起始的逆向迭代器,rend、crend指向末尾的逆向迭代器。代码示例:

cpp 复制代码
std::list<float> l = {1.1f, 2.1f, 3.1f};
for (auto iter = l.rbegin(); iter != l.rend(); ++iter)
{
    *iter += 27.f;
}

for (auto iter = l.crbegin(); iter != l.crend(); ++iter)
{
    std::cout << "num is: " << *iter << std::endl;
}

输出结果:

bash 复制代码
num is: 30.1
num is: 29.1
num is: 28.1

容量

empty

检查list是否为空。示例代码:

cpp 复制代码
std::list<float> l1 = {1.1f, 2.1f, 3.1f};
std::list<float> l2;
std::cout << std::boolalpha;
std::cout << "l1 empty: " << l1.empty() << std::endl;
std::cout << "l2 empty: " << l2.empty() << std::endl;

输出结果:

bash 复制代码
l1 empty: false
l2 empty: true

size

获取list元素的个数。代码示例:

cpp 复制代码
std::list<float> l1 = {1.1f, 2.1f, 3.1f};
std::list<float> l2;
std::cout << "l1 size = " << l1.size() << std::endl;
std::cout << "l2 size = " << l2.size() << std::endl;

输出结果:

bash 复制代码
l1 size = 3
l2 size = 0

max_size

返回可以容纳的最大元素个数。代码示例:

cpp 复制代码
struct MyStruct
{
    double num1;
    double num2;
    double num3;
    double num4;
};

std::list<float> l1;
std::list<double> l2;
std::list<MyStruct> l3;
std::cout << "l1 max size = " << l1.max_size() << std::endl;
std::cout << "l2 max size = " << l2.max_size() << std::endl;
std::cout << "l3 max size = " << l3.max_size() << std::endl;

输出结果:

bash 复制代码
l1 max size = 768614336404564650
l2 max size = 768614336404564650
l3 max size = 384307168202282325

修改器

clear

清除所有的元素。代码示例:

cpp 复制代码
std::list<float> l(3, 1.f);
std::cout << std::boolalpha;
std::cout << "l empty: " << l.empty() << std::endl;
l.clear();
std::cout << "l empty: " << l.empty() << std::endl;

输出结果:

bash 复制代码
l empty: false
l empty: true

insert

在指定的位置插入元素。代码示例:

cpp 复制代码
auto print_func = [](const std::list<float>& list)
{
    for (auto i : list)
    {
        std::cout << i << " ";
    }
    std::cout << std::endl;
};

std::vector<float> vec{40.1f, 40.2f};

std::list<float> l = {1.1f, 1.2f, 1.3f};
print_func(l);
l.insert(l.begin(), 15.7f);
print_func(l);
l.insert(std::next(l.begin(), 2), 3, 27.9f);
print_func(l);
l.insert(std::next(l.begin(), 1), vec.begin(), vec.end());
print_func(l);
l.insert(std::next(l.begin(), 1), {70.5f, 75.5f, 71.5f});
print_func(l);

输出结果:

bash 复制代码
1.1 1.2 1.3 
15.7 1.1 1.2 1.3 
15.7 1.1 27.9 27.9 27.9 1.2 1.3 
15.7 40.1 40.2 1.1 27.9 27.9 27.9 1.2 1.3 
15.7 70.5 75.5 71.5 40.1 40.2 1.1 27.9 27.9 27.9 1.2 1.3 

emplace

在指定位置一个元素。代码示例:

cpp 复制代码
struct MyStruct
{
    MyStruct(float num1, int num2)
    {
        std::cout << "construct " << num1 << " " << num2 << std::endl;
    }
};

std::list<MyStruct> f;
f.emplace(f.begin(), 5.5f, 20);

输出结果:

cpp 复制代码
construct 5.5 20

erase

删除指定位置的元素。代码示例:

cpp 复制代码
auto print_func = [](const std::list<float>& list)
{
    for (auto i : list)
    {
        std::cout << i << " ";
    }
    std::cout << std::endl;
};

std::list<float> l = {1.1f, 1.2f, 1.3f, 1.5f, 1.6f, 1.7f, 1.8f};
print_func(l);
l.erase(std::next(l.begin(), 1));
print_func(l);
l.erase(std::next(l.begin(), 1), std::next(l.begin(), 5));
print_func(l);

输出结果:

bash 复制代码
1.1 1.2 1.3 1.5 1.6 1.7 1.8 
1.1 1.3 1.5 1.6 1.7 1.8 
1.1 1.8 

push_back

将元素添加到末尾。代码示例:

cpp 复制代码
auto print_func = [](const std::list<float>& list)
{
    for (auto i : list)
    {
        std::cout << i << " ";
    }
    std::cout << std::endl;
};

std::list<float> l = {1.1f, 1.2f};
l.push_back(1.3f);
l.push_back(1.4f);
print_func(l);

输出结果:

bash 复制代码
1.1 1.2 1.3 1.4 

emplace_back

在列表末尾构造一个元素。代码示例:

cpp 复制代码
struct MyStruct
{
    MyStruct(float num1, int num2)
    {
        std::cout << "construct " << num1 << " " << num2 << std::endl;
    }
};

std::list<MyStruct> l;
l.emplace_back(1.5f, 17);
l.emplace_back(2.3f, 4);

输出结果:

bash 复制代码
construct 1.5 17
construct 2.3 4

pop_back

移除末尾的元素。代码示例:

cpp 复制代码
std::list<float> l = {1.1f, 1.2f, 1.3f};
std::cout << "l back is: " << l.back() << std::endl;
l.pop_back();
std::cout << "l back is: " << l.back() << std::endl;

输出结果:

bash 复制代码
l back is: 1.3
l back is: 1.2

push_front

将元素添加到起始位置。代码示例:

cpp 复制代码
std::list<float> l = {1.1f, 1.2f, 1.3f};
std::cout << "l front is: " << l.front() << std::endl;
l.push_front(17.7f);
std::cout << "l front is: " << l.front() << std::endl;

输出结果:

bash 复制代码
l front is: 1.1
l front is: 17.7

emplace_front

在列表起始位置构造一个元素。代码示例:

cpp 复制代码
struct MyStruct
{
    MyStruct(float num1, int num2)
    {
        std::cout << "construct " << num1 << " " << num2 << std::endl;
    }
};

std::list<MyStruct> l;
l.emplace_front(2.7f, 17);
l.emplace_front(15.1f, 13);

输出结果:

bash 复制代码
construct 2.7 17
construct 15.1 13

pop_front

移除列表的首个元素。代码示例:

cpp 复制代码
std::list<float> l = {1.1f, 1.2f, 1.3f};
std::cout << "l front is: " << l.front() << std::endl;
l.pop_front();
std::cout << "l front is: " << l.front() << std::endl;

输出结果:

bash 复制代码
l front is: 1.1
l front is: 1.2

resize

重新设置元素的个数。代码示例:

cpp 复制代码
std::list<float> l = {1.1f, 1.2f, 1.3f};
std::cout << "l size is: " << l.size() << std::endl;
l.resize(2);
std::cout << "l size is: " << l.size() << std::endl;
l.resize(20);
std::cout << "l size is: " << l.size() << std::endl;

输出结果:

bash 复制代码
l size is: 3
l size is: 2
l size is: 20

swap

交换两个列表的元素内容。代码示例:

cpp 复制代码
std::list<float> l1 = {1.1f, 1.2f, 1.3f};
std::list<float> l2 = {2.1f, 2.2f};
l1.swap(l2);
std::cout << "l1 size = " << l1.size() << std::endl;
std::cout << "l2 size = " << l2.size() << std::endl;

输出结果:

bash 复制代码
l1 size = 2
l2 size = 3

操作

sort

对元素进行排序。代码示例:

cpp 复制代码
auto print_func = [](const std::list<int>& list)
{
    for (auto i : list)
    {
        std::cout << i << " ";
    }
    std::cout << std::endl;
};

std::list<int> l = {7, 17, 5, 47, 25};
print_func(l);

l.sort();
print_func(l);

l.sort(
    [](int a, int b)
    {
        return a > b;
    });
print_func(l);

输出结果:

bash 复制代码
7 17 5 47 25 
5 7 17 25 47 
47 25 17 7 5 

merge

合并两个有序的列表。代码示例:

cpp 复制代码
auto print_func = [](const std::list<int>& list)
{
    for (auto i : list)
    {
        std::cout << i << " ";
    }
    std::cout << std::endl;
};

{
    std::list<int> l1 = {1, 5, 7, 19};
    std::list<int> l2 = {2, 3, 14, 15};
    l1.merge(l2);
    print_func(l1);
}

{
    std::list<int> l1 = {1, 5, 7, 19};
    std::list<int> l2 = {2, 3, 14, 15};
    l1.merge(l2,
             [](int a, int b)
             {
                 return a > b;
             });
    print_func(l1);
}

输出结果:

bash 复制代码
1 2 3 5 7 14 15 19 
2 3 14 15 1 5 7 19 

splice

将另一个列表中的一些元素移动到this列表指定的位置。代码示例:

cpp 复制代码
auto print_func = [](std::string tag, const std::list<float>& list)
{
    std::cout << tag;
    for (auto i : list)
    {
        std::cout << i << " ";
    }
    std::cout << std::endl;
};

{
    std::list<float> l1 = {1.5f, 5.5f, 7.5f, 19.5f};
    std::list<float> l2 = {2.4f, 3.4f, 14.4f, 15.4f};
    l1.splice(l1.begin(), l2);
    print_func("l1 = ", l1);
    print_func("l2 = ", l2);
}

{
    std::list<float> l1 = {1.5f, 5.5f, 7.5f, 19.5f};
    std::list<float> l2 = {2.4f, 3.4f, 14.4f, 15.4f};
    l1.splice(std::next(l1.begin(), 2), l2, std::next(l2.begin(), 1));
    print_func("l1 = ", l1);
    print_func("l2 = ", l2);
}

{
    std::list<float> l1 = {1.5f, 5.5f, 7.5f, 19.5f};
    std::list<float> l2 = {2.4f, 3.4f, 14.4f, 15.4f};
    l1.splice(l1.begin(), l2, l2.begin(), std::next(l2.begin(), 2));
    print_func("l1 = ", l1);
    print_func("l2 = ", l2);
}

输出结果:

bash 复制代码
l1 = 2.4 3.4 14.4 15.4 1.5 5.5 7.5 19.5 
l2 = 
l1 = 1.5 5.5 3.4 7.5 19.5 
l2 = 2.4 14.4 15.4 
l1 = 2.4 3.4 1.5 5.5 7.5 19.5 
l2 = 14.4 15.4 

remove、remove_if

remove移除等于指定值的元素。remove_if移除满足指定要求的元素。代码示例:

cpp 复制代码
auto print_func = [](const std::list<int>& list)
{
    for (auto i : list)
    {
        std::cout << i << " ";
    }
    std::cout << std::endl;
};

std::list<int> l = {5, 9, 17, 27, 15, 5, 5};
print_func(l);

l.remove(5);
print_func(l);

l.remove_if(
    [](int n)
    {
        return n > 15;
    });
print_func(l);

输出结果:

bash 复制代码
5 9 17 27 15 5 5 
9 17 27 15 
9 15 

reverse

反转元素的顺序。代码示例:

cpp 复制代码
auto print_func = [](const std::list<float>& list)
{
    for (auto i : list)
    {
        std::cout << i << " ";
    }
    std::cout << std::endl;
};

std::list<float> l = {1.1f, 3.1f, 19.1f, 7.1f};
print_func(l);
l.reverse();
print_func(l);

输出结果:

bash 复制代码
1.1 3.1 19.1 7.1 
7.1 19.1 3.1 1.1 

unique

删除连续的重复元素。代码示例:

cpp 复制代码
auto print_func = [](const std::list<int>& list)
{
    for (auto i : list)
    {
        std::cout << i << " ";
    }
    std::cout << std::endl;
};

std::list<int> l = {1, 3, 3, 17, 7, 3, 17, 17, 19, 1, 3, 1};
print_func(l);
l.unique();
print_func(l);

输出结果:

bash 复制代码
1 3 3 17 7 3 17 17 19 1 3 1 
1 3 17 7 3 17 19 1 3 1 

非成员函数

比较运算符

operator==,!=,<,<=,>,>=用于比较两个forward_list。代码示例:

cpp 复制代码
std::list<int> l1 = {1, 2, 3, 4};
std::list<int> l2 = {1, 5};
std::cout << std::boolalpha;
std::cout << "l1 == l2: " << (l1 == l2) << std::endl;
std::cout << "l1 != l2: " << (l1 != l2) << std::endl;
std::cout << "l1 <  l2: " << (l1 < l2) << std::endl;
std::cout << "l1 <= l2: " << (l1 <= l2) << std::endl;
std::cout << "l1 >  l2: " << (l1 > l2) << std::endl;
std::cout << "l1 >= l2: " << (l1 >= l2) << std::endl;

输出结果:

bash 复制代码
l1 == l2: false
l1 != l2: true
l1 <  l2: true
l1 <= l2: true
l1 >  l2: false
l1 >= l2: false

swap

交换两个列表的元素内容。示例代码:

cpp 复制代码
std::list<float> l1 = {1.5f, 2.5f};
std::list<float> l2 = {17.1f, 15.1f, 27.1f};
std::swap(l1, l2);
std::cout << "l1 front is: " << l1.front() << std::endl;
std::cout << "l2 front is: " << l2.front() << std::endl;

输出结果:

bash 复制代码
l1 front is: 17.1
l2 front is: 1.5

erase、erase_if

erase删除等于指定值的元素,erase_if删除满足条件的元素。代码示例:

cpp 复制代码
auto print_func = [](const std::list<int>& list)
{
    for (auto i : list)
    {
        std::cout << i << " ";
    }
    std::cout << std::endl;
};

std::list<int> l = {5, 7, 17, 29, 7, 7, 35};
print_func(l);

std::erase(l, 7);
print_func(l);

std::erase_if(l,
              [](int a)
              {
                  return a > 17;
              });
print_func(l);

输出结果:

bash 复制代码
5 7 17 29 7 7 35 
5 17 29 35 
5 17 
相关推荐
WWJA王文举6 小时前
I²C通信完整流程详解:START、地址、ACK、数据、Repeated START和STOP一次讲透
c语言·开发语言
zhanghaha13147 小时前
Python进阶教程:6_JSON 数据解析 —— 新手完全指南
开发语言·python·json
ShineWinsu8 小时前
对于C++:C++11中lambda、function、bind的解析
c++·面试·笔试·开发·lambda·bind·function
码匠许师傅8 小时前
【C++ 面试真题】聊聊 C++ 的拷贝构造与拷贝赋值
java·c++·面试
qq_448011168 小时前
C语言中的动态内存分配
c语言·开发语言·php
旖旎夜光9 小时前
LeetCode 3:无重复字符的最长子串(滑动窗口) —— 题解
数据结构·c++·算法·leetcode·滑动窗口
汉字萌萌哒9 小时前
2024CSP-J入门级C++真题详解
开发语言·c++
arbboter9 小时前
【网络工具】NetProxy网络代理用户手册
开发语言·网络·c#·网络代理·网络异常·代理工具
hy.z_7779 小时前
【C++】13. 继承
c++
汉字萌萌哒10 小时前
2019CCF-CSP入门级C++试题解析
java·开发语言·c++