Cheyne's Blog


  • Home
  • Archive
  • Categories
  •    

© 2025 John Doe

Theme Typography by Makito

Proudly published with Hexo

现代C++32讲:容器汇编 I - 比较简单的若干容器

Posted at 2025-08-09 C++ 

String

一般不建议在接口中使用const string&,除非确实知道调用者已经持有 string:如果函数里不对字符串做复杂处理的话,使用const char*可以避免在调用者只有 C 字符串时编译器自动构造 string,这种额外的构造和析构成本不低。
反过来,如果实现较为复杂、希望使用 string 的成员函数的话,就应该考虑下面的策略:

  • 如果不修改字符串的内容,使用const string&或 C++17 的string_view作为参数类型。后者是最理想的情况,因为即使在只有 C 字符串的情况,也不会引发不必要的内存复制。
  • 如果需要在函数内部修改字符串内容、但又不影响调用者的该字符串,使用string作为参数类型(自动拷贝)。
  • 如果需要改变调用者的字符串内容,使用string&作为参数类型(通常不推荐)。

vector

当内存重分配,或者元素位置移动时,vector 通常保证强异常安全性,如果元素类型没有提供一个保证不抛异常的移动构造函数,vector 通常会使用拷贝构造函数。
因此,对于拷贝代价较高的自定义元素类型,我们应当定义拷贝构造函数,并标记其为noexcept,或只在容器中放置对象的智能指针。

deque

image.png
deque 中的元素只是部分连续的,因此没法提供data成员函数。
每一段存储的大小相等,deque 支持使用下标访问容器元素,大致相当于index[i/chunk_size][i%chunk_size]。

list

C++中的 list 代表双向链表。
某些标准算法在 list 上会出问题,list 提供了成员函数作为替代。

1
2
3
4
5
6
list<int> lst{1, 7, 2, 8, 3};
vector<int> vec{1, 7, 2, 8, 3};

sort(vec.begin(), vec.end()); // 正常
sort(lst.begin(), lst.end()); // 出错
lst.sort(); // 正常

forward_list

单向链表。

queue

它不是完整的实现,而是依赖于某个现有的容器,被称为容器适配器。
queue 缺省用 deque 来实现。

stack

stack 缺省也是用 deque 来实现,但它的概念和 vector 更相似。

扩展

Q: 为什么stack(或 queue)的 pop 函数返回类型为 void,而不是直接返回容器的 top(或 front)成员?
A: 为保证强异常安全性,如果元素类型没有提供一个保证不抛出异常的移动构造函数,通常会使用拷贝构造函数。而 C++98 还没有移动构造的概念,所以如果返回成员,就必须使用拷贝构造函数,这时候分配空间可能出错,导致构造失败,要抛出异常。因此没必要返回成员。

Share 

 Previous post: 现代C++32讲:容器汇编 II - 需要函数对象的容器 Next post: 现代C++32讲:右值和移动究竟解决了什么问题? 

© 2025 John Doe

Theme Typography by Makito

Proudly published with Hexo