容器库(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 
相关推荐
牛奔25 分钟前
Go 如何避免频繁抢占?
开发语言·后端·golang
寻星探路4 小时前
【深度长文】万字攻克网络原理:从 HTTP 报文解构到 HTTPS 终极加密逻辑
java·开发语言·网络·python·http·ai·https
lly2024066 小时前
Bootstrap 警告框
开发语言
2601_949146536 小时前
C语言语音通知接口接入教程:如何使用C语言直接调用语音预警API
c语言·开发语言
曹牧7 小时前
Spring Boot:如何测试Java Controller中的POST请求?
java·开发语言
在路上看风景7 小时前
19. 成员初始化列表和初始化对象
c++
KYGALYX7 小时前
服务异步通信
开发语言·后端·微服务·ruby
zmzb01037 小时前
C++课后习题训练记录Day98
开发语言·c++
念风零壹7 小时前
C++ 内存避坑指南:如何用移动语义和智能指针解决“深拷贝”与“内存泄漏”
c++
猫头虎8 小时前
如何排查并解决项目启动时报错Error encountered while processing: java.io.IOException: closed 的问题
java·开发语言·jvm·spring boot·python·开源·maven