目录
- 1 概述
- 2 使用实例
- 3 接口使用
- 3.1 construct
- 3.2 assigns
- 3.3 iterators
- 3.4 capacity
- 3.5 access
- 3.6 assign
- 3.7 emplace_front
- 3.8 push_front
- 3.9 pop_front
- 3.10 emplace_back
- 3.11 push_back
- 3.12 pop_back
- 3.13 emplace
- 3.14 insert
- 3.15 erase
- 3.16 swap
- 3.17 resize
- 3.18 clear
- 3.19 splice
- 3.20 remove
- 3.21 remove_if
- 3.22 unique
- 3.23 merge
- 3.24 sort
- 3.25 reverse
- 3.26 get_allocator
1 概述
列表是序列容器,允许在序列中的任何位置进行恒定时间的插入和擦除操作,以及双向迭代。
列表容器被实现为双链表;双链接列表可以将它们所包含的每个元素存储在不同且不相关的存储位置。排序是通过与每个元素的关联在内部保持的,其中链接到它前面的元素,链接到它后面的元素。
它们与forward_list非常相似:主要区别在于forward_liist对象是单链表,因此它们只能向前迭代,以换取更小、更高效。
与其他基本标准序列容器(数组、向量和deque)相比,列表在插入、提取和移动容器中已经获得迭代器的任何位置的元素方面通常表现得更好,因此在密集使用这些元素的算法(如排序算法)中也表现得更好。
与这些其他序列容器相比,list和forward_list的主要缺点是它们缺乏通过位置对元素的直接访问;例如,要访问列表中的第六个元素,必须从已知位置(如开始或结束)迭代到该位置,这需要在这些位置之间的距离上花费线性时间。它们还消耗一些额外的内存来保持与每个元素相关联的链接信息(这可能是小型元素的大列表的重要因素)。
其类图如下:

2 使用实例
void ListSuite::access()
{
int array[] = { 1, 2, 3, 4, 5 };
std::list<int> a(array, array + ARRAY_SIZE(array));
TEST_ASSERT_EQUALS(1, a.front())//size of a must more than 0
TEST_ASSERT_EQUALS(5, a.back()) //size of a must more than 0
}
3 接口使用
3.1 construct
std::list<int> getList(int size, int value)
{
return std::list<int>(size, value);
}
void ListSuite::construct()
{
std::list<int> a;
std::list<int> b(4); // 0 0 0 0
std::list<int> c(4, 5);// 5 5 5 5
std::list<int> d({1, 2, 3, 4, 5});
std::list<int> e(d.begin(), d.end());
std::list<int> f(d);
std::list<int> g(getList(6, 8));
TEST_ASSERT_EQUALS(0, a.size())
TEST_ASSERT_EQUALS(4, b.size())
TEST_ASSERT_EQUALS(4, c.size())
TEST_ASSERT_EQUALS(5, d.size())
TEST_ASSERT_EQUALS(5, e.size())
TEST_ASSERT_EQUALS(5, f.size())
TEST_ASSERT_EQUALS(6, g.size())
}
3.2 assigns
void ListSuite::assigns()
{
std::list<int> a;
std::list<int> b;
std::list<int> c;
a = { 1, 2, 3, 4, 5 };
b = a;
c = getList(5, 10);
TEST_ASSERT_EQUALS(5, a.size())
TEST_ASSERT_EQUALS(5, b.size())
TEST_ASSERT_EQUALS(5, c.size())
}
3.3 iterators
#define ARRAY_SIZE(array) sizeof(array) / sizeof(array[0])
void ListSuite::iterators()
{
int array[] = { 1, 2, 3, 4, 5 };
int rarray[] = { 5, 4, 3, 2, 1 };
std::list<int> a(array, array + ARRAY_SIZE(array));
int index = 0;
for(auto it = a.begin(); it != a.end(); ++it)
{
TEST_ASSERT_EQUALS(array[index++], *it)
}
index = 0;
for(auto it = a.cbegin(); it != a.cend(); ++it)
{
TEST_ASSERT_EQUALS(array[index++], *it)
}
index = 0;
for(auto it = a.rbegin(); it != a.rend(); ++it)
{
TEST_ASSERT_EQUALS(rarray[index], *it)
rarray[index] = rarray[index] * 2;
*it = rarray[index++];
}
index = 0;
for(auto it = a.crbegin(); it != a.crend(); ++it)
{
TEST_ASSERT_EQUALS(rarray[index++], *it)
}
}
3.4 capacity
void ListSuite::capacity()
{
std::list<int> a;
std::list<int> b({1, 2, 3, 4, 5});
TEST_ASSERT_EQUALS(0, a.size())
TEST_ASSERT_EQUALS(5, b.size())
TEST_ASSERT_EQUALS(true, a.empty())
TEST_ASSERT_EQUALS(false, b.empty())
TEST_ASSERT_EQUALS(a.max_size(), b.max_size())
}
3.5 access
void ListSuite::access()
{
int array[] = { 1, 2, 3, 4, 5 };
std::list<int> a(array, array + ARRAY_SIZE(array));
TEST_ASSERT_EQUALS(1, a.front())//size of a must more than 0
TEST_ASSERT_EQUALS(5, a.back()) //size of a must more than 0
}
3.6 assign
void ListSuite::assign()
{
std::list<int> a;
std::list<int> b;
std::list<int> c;
a.assign({ 1, 2, 3, 4, 5 });
b.assign(a.begin(), a.end());
c.assign(4, 5);
TEST_ASSERT_EQUALS(5, a.size())
TEST_ASSERT_EQUALS(5, b.size())
TEST_ASSERT_EQUALS(4, c.size())
}
3.7 emplace_front
void ListSuite::emplace_front()
{
std::list<std::string> names;
names.emplace_front("james"); //james
TEST_ASSERT_EQUALS("james", names.front())
names.emplace_front("jim"); //james jim
TEST_ASSERT_EQUALS("jim", names.front())
}
3.8 push_front
void ListSuite::push_front()
{
int array[] = { 1, 2, 3, 4, 5 };
std::list<int> a;
for(size_t i = 0; i < ARRAY_SIZE(array); i++)
a.push_front(array[i]);
int index = 0;
for(auto it = a.rbegin(); it != a.rend(); ++it)
TEST_ASSERT_EQUALS(array[index++], *it)
}
3.9 pop_front
void ListSuite::pop_front()
{
std::list<int> a({1, 2, 3, 4, 5});
TEST_ASSERT_EQUALS(1, a.front())
a.pop_front();
TEST_ASSERT_EQUALS(2, a.front())
a.pop_front();
TEST_ASSERT_EQUALS(3, a.front())
a.pop_front();
TEST_ASSERT_EQUALS(4, a.front())
a.pop_front();
TEST_ASSERT_EQUALS(5, a.front())
a.pop_front();
TEST_ASSERT_EQUALS(true, a.empty())
if(!a.empty())
a.pop_front();//??
TEST_ASSERT_EQUALS(true, a.empty())
}
3.10 emplace_back
void ListSuite::emplace_back()
{
std::list<std::string> names;
names.emplace_back("james"); //james
TEST_ASSERT_EQUALS("james", names.back())
names.emplace_back("jim"); //james jim
TEST_ASSERT_EQUALS("jim", names.back())
}
3.11 push_back
void ListSuite::push_back()
{
int array[] = { 1, 2, 3, 4, 5 };
std::list<int> a;
for(size_t i = 0; i < ARRAY_SIZE(array); i++)
a.push_back(array[i]);
int index = 0;
for(auto it = a.begin(); it != a.end(); ++it)
TEST_ASSERT_EQUALS(array[index++], *it)
}
3.12 pop_back
void ListSuite::pop_back()
{
std::list<int> a({1, 2, 3, 4, 5});
TEST_ASSERT_EQUALS(5, a.back())
a.pop_back();
TEST_ASSERT_EQUALS(4, a.back())
a.pop_back();
TEST_ASSERT_EQUALS(3, a.back())
a.pop_back();
TEST_ASSERT_EQUALS(2, a.back())
a.pop_back();
TEST_ASSERT_EQUALS(1, a.back())
a.pop_back();
TEST_ASSERT_EQUALS(true, a.empty())
if(!a.empty())
a.pop_back();//??
TEST_ASSERT_EQUALS(true, a.empty())
}
3.13 emplace
void ListSuite::emplace()
{
std::list<std::string> names;
auto it = names.emplace(names.begin(), "james"); //james
TEST_ASSERT_EQUALS("james", *it)
it = names.emplace(names.end(), "jim"); //james jim
TEST_ASSERT_EQUALS("jim", *it)
}
3.14 insert
void ListSuite::insert()
{
std::list<std::string> names;
std::string name("James");
auto it = names.insert(names.begin(), name);//James
TEST_ASSERT_EQUALS(name, *it)
it = names.insert(names.end(), 2, "Tom"); //James Tom Tom
TEST_ASSERT_EQUALS("Tom", *it)
it = names.insert(names.end(), "Peter"); //James Tom Tom Peter
TEST_ASSERT_EQUALS("Peter", *it)
it = names.insert(names.end(), {"Jim", "Rose", }); //James Tom Tom Peter Jim Rose
TEST_ASSERT_EQUALS("Jim", *it)
}
3.15 erase
void ListSuite::erase()
{
std::list<int> a({1, 2, 3, 4, 5});
auto it1 = a.begin();
auto it2 = a.begin();
std::advance(it1, 1);
std::advance(it2, 4);
TEST_ASSERT_EQUALS(2, *it1)
TEST_ASSERT_EQUALS(5, *it2)
auto it = a.erase(it1);//1 3 4 5
TEST_ASSERT_EQUALS(3, *it)
it = a.erase(it2);//1 3 4
TEST_ASSERT_EQUALS(true, it == a.end())
it1 = a.begin();
std::advance(it1, 1);
TEST_ASSERT_EQUALS(3, *it1)
it = a.erase(a.begin(), it1);
TEST_ASSERT_EQUALS(4, *it)
}
3.16 swap
void ListSuite::swap()
{
std::list<int> a({1, 2, 3, 4, 5});
std::list<int> b;
TEST_ASSERT_EQUALS(5, a.size())
TEST_ASSERT_EQUALS(0, b.size())
a.swap(b);
TEST_ASSERT_EQUALS(0, a.size())
TEST_ASSERT_EQUALS(5, b.size())
}
3.17 resize
void ListSuite::resize()
{
std::list<int> a;
a.resize(5, 10); //10 10 10 10 10
for(auto it = a.begin(); it != a.end(); ++it)
TEST_ASSERT_EQUALS(10, *it);
a.resize(8); //10 10 10 10 10 0 0 0
auto end = a.begin();
std::advance(end, 5);
for(auto it = a.begin(); it != end; ++it)
TEST_ASSERT_EQUALS(10, *it);
for(auto it = end; it != a.end(); ++it)
TEST_ASSERT_EQUALS(0, *it);
a.resize(10, 20); //10 10 10 10 10 0 0 0 20 20
auto begin = a.begin();
std::advance(begin, 10);
for(auto it = begin; it != a.end(); ++it)
TEST_ASSERT_EQUALS(20, *it);
}
3.18 clear
void ListSuite::clear()
{
std::list<int> a({1, 2, 3, 4, 5});
TEST_ASSERT_EQUALS(5, a.size())
a.clear();
TEST_ASSERT_EQUALS(0, a.size())
}
3.19 splice
void ListSuite::splice()
{
std::list<int> a({1, 2, 3, 4, 5});
std::list<int> b({6, 7, 8, 9, 10});
a.splice(a.end(), b);
TEST_ASSERT_EQUALS(10, a.size())
TEST_ASSERT_EQUALS(0, b.size())
b.splice(b.begin(), a, a.begin());//1
TEST_ASSERT_EQUALS(1, b.front())
b.splice(b.end(), a, a.begin(), a.end());
TEST_ASSERT_EQUALS(0, a.size())
TEST_ASSERT_EQUALS(10, b.size())
}
说明:
- 拼接两个list,不要求两个表是排好序的
- 拼接时不是复制,而是移动,作为为参数容器中对应元素将会被删除。
3.20 remove
void ListSuite::remove()
{
std::list<int> a({1, 2, 3, 3, 4, 5});
TEST_ASSERT_EQUALS(6, a.size())
a.remove(3);
TEST_ASSERT_EQUALS(4, a.size())
}
说明:
- 删除list中等于指定值的所有元素。
3.21 remove_if
bool single_num(const int& value) { return value < 10; }
struct is_even
{
bool operator()(const int& value) { return value % 2 == 0; }
};
void ListSuite::remove_if()
{
std::list<int> a({15, 36, 7, 17, 20, 39, 4, 1});
a.remove_if(single_num);//15, 36, 17, 20, 39
TEST_ASSERT_EQUALS(5, a.size())
a.remove_if(is_even());//15, 17, 39
TEST_ASSERT_EQUALS(3, a.size())
a.remove_if([](const int& value){ return value > 20; }); // 15 , 17
TEST_ASSERT_EQUALS(2, a.size())
}
说明:
- 删除list中符合谓词函数的所有元素
3.22 unique
void ListSuite::unique()
{
std::list<int> a({ 1, 2, 3, 3, 4, 3, 5, 6 , 6});
TEST_ASSERT_EQUALS(9, a.size())
a.unique();//1 2 3 4 3 5 6
TEST_ASSERT_EQUALS(7, a.size())
a.sort();
a.unique();//1 2 3 4 5 6
TEST_ASSERT_EQUALS(6, a.size())
std::list<float > b{ 1.2, 1.5, 2.2, 2.3, 3.2, 3.3 };
b.unique([](const float& l, const float& r) { return int(l) == int(r); }); // 1.2 2.2 3.2
TEST_ASSERT_EQUALS(3, b.size())
}
说明:
- 该函数删除list中相同元素,不过前提是list是排好序的
- 如果是无序list,只会删除相邻相同的元素,如果相同元素在list中不相邻,将不会被删除。
3.23 merge
void ListSuite::merge()
{
std::list<int> a{1, 2, 3, 4, 5};
std::list<int> b{6, 7, 8, 9, 10};
a.sort();
b.sort();
a.merge(b);
TEST_ASSERT_EQUALS(10, a.size())
TEST_ASSERT_EQUALS(0, b.size())
}
说明:
- 合并两个list,前期是两个list是排好序的,合并后也是排好序的。
3.24 sort
void ListSuite::sort()
{
int array[] = { 1, 5, 6, 7, 8, 15, 32 };
std::list<int> a{5, 1, 7, 8, 6, 15, 32};
a.sort();
int index = 0;
for(auto it = a.begin(); it != a.end(); ++it)
TEST_ASSERT_EQUALS(array[index++], *it)
a.sort([](int const&l, int const&r ){ return l > r; });
index = 0;
for(auto it = a.rbegin(); it != a.rend(); ++it)
TEST_ASSERT_EQUALS(array[index++], *it)
}
说明:
- 默认谓词是小于,按升序排序
- 可以指定为为大于,按降序排序
3.25 reverse
void ListSuite::reverse()
{
int array[] = { 1, 2, 3, 4, 5 };
std::list<int> a(array, array +ARRAY_SIZE(array));
a.reverse();
int index = 0;
for(auto it = a.rbegin(); it != a.rend(); ++it)
TEST_ASSERT_EQUALS(array[index++], *it)
}
3.26 get_allocator
void ListSuite::get_allocator()
{
std::list<int> a;
auto allocator = a.get_allocator();
int* p = allocator.allocate(5);
allocator.deallocate(p, 5);
try
{
p = allocator.allocate(allocator.max_size() + 1);
}
catch(...)
{
p = nullptr;
}
TEST_ASSERT_EQUALS(true, p == nullptr)
}

338

被折叠的 条评论
为什么被折叠?



