1 std::function

C++11 std::function 是一种通用、多态的函数封装,它的实例可以对任何可以调用的目标实体进行存储、复制和调用操作,它也是对 C 中现有的可调用实体的一种类型安全的包裹(相对来说,函数指针的调⽤不是类型安全的),换句话说,就是函数的容器。当我们有了函数的容器之后便能够更加方便的将函数、函数指针作为对象进行处理。

example_9 code

  1. #include <iostream>
  2. #include <functional> //必须头文件
  3. int foo(int a)
  4. {
  5. return a;
  6. }
  7. int main()
  8. {
  9. std::function<int(int)> func = foo; //包装了一个返回值为int,参数为int的函数
  10. int important = 10;
  11. std::function<int(int)> func2 = [&](int value)->int{
  12. return 1 + value + important;
  13. };
  14. std::cout<<func(10)<<std::endl;
  15. std::cout<<func2(10)<<std::endl;
  16. }

2 std::array

std::array 保存在栈内存中,相比堆内存中的 std::vector,我们就能够灵活的访问这里面的元素,从而获得更好的性能。使用std::array能够让代码变得更加现代,且封装了一些操作函数,同时还能够友好的使用标准库中的容器算法等等,比如 std::sort。

语法格式:

  1. std::array<int, 4> arr{1, 2, 3, 4}; //固定大小,不能隐式转为指针
  2. // C风格接口传参
  3. // foo (arr , arr . size ()); // 非 法 , 无 法 隐 式 转 换
  4. foo(&arr[0], arr.size()); //显示转换为指针
  5. foo(arr.data(), arr.size()); //显示转换为指针
  6. // 使用std::sort
  7. std::sort(arr.begin(), arr.end());

3 std::tuple

关于元组的使用有三个核心的函数:

  1. std::make_tuple: 构造元组
  2. std::get: 获得元组某个位置的值
  3. std::tie: 元组拆包

例子example_11 code:

  1. #include <iostream>
  2. #include <tuple>
  3. #include <string>
  4. int main()
  5. {
  6. auto t = std::make_tuple(3.8, "A", "Barret Ren");
  7. //get获取元素
  8. std::cout<<std::get<0>(t)<<std::endl;
  9. std::cout<<std::get<1>(t)<<std::endl;
  10. std::cout<<std::get<2>(t)<<std::endl;
  11. //tie进行拆包
  12. double a;
  13. std::string b;
  14. std::string c;
  15. std::tie(a, b, c)=t;
  16. std::cout<<c<<std::endl;
  17. }

std::tuple 虽然有效,但是标准库提供的功能有限,没办法满足运行期索引和迭代的需求,好在我们还有其他的方法可以实现。需要boost库的支持。

4 std::size()

C++17开始,可以使用std::size()获取传统C数组的个数。
int myArray[]={1,2,3,4};
std::cout<<std::size(myArray)<<std::endl;

5 std::optional

optional意为可选值,需要传入一个类型,表示该类型的值存在或不存在。通常用于函数返回值,比如下面的用法:

  1. //std::optional使用示例,表示可以存在或不存在的值
  2. #include <iostream>
  3. #include <optional>
  4. using namespace std;
  5. //定义一个函数,返回值是可选值,既可以是int,也可以是其他非类型
  6. optional<int> getData(bool it)
  7. {
  8. if (it)
  9. return 42;
  10. return nullopt;
  11. }
  12. int main()
  13. {
  14. //调用函数,保存返回值
  15. optional<int> data1{getData(true)};
  16. optional<int> data2{getData(false)};
  17. //判断变量是否有值(两种方式),如果有打印值
  18. if (data1.has_value())
  19. {
  20. cout << data1.value() << endl;
  21. }
  22. if (data2)
  23. {//不经判断直接访问会抛出exception
  24. cout << *data2 << endl;
  25. }
  26. //data2没有值,但可以通过以下方式打印它保存了什么
  27. cout << "what is in data? " << data2.value_or(0) << endl;
  28. }

6 emplace操作

C++11开始支持emplace操作,emplace和push_back/insert之类的修改方式不同的是,emplace直接占用容器的内存空间创建需要保存的对象(原位调用构造函数),不需要提前创建对象再复制或移动(move)到容器中
emplace主要有以下基本成员函数,不同类型的容器支持情况不同:

  • emplace(const_iterator pos, Args&&... args):直接于 pos 前插入元素到容器中
  • emplace_after(const_iterator pos, Args&&... args):在容器中的指定位置后插入新元素
  • emplace_hint(const_iterator hint, Args&&... args):插入新元素到尽可能接近恰在 hint 前的位置
  • emplace_front(Args&&... args):插入新元素到容器起始
    • C++11返回void
    • C++17开始返回构造对象的引用
  • emplace_back(Args&&... args):添加新元素到容器尾
    • C++11返回void
    • C++17开始返回构造对象的引用

      7 std::span

      span是C++20引入,表示连续相邻的序列,可以用于表示vector,array和C原始数组的一部分或全部,类似于string_view
      span主要包含两个成员:指向容器类型T的指针和表示的范围大小。span只是顺序序列容器的一个指针视图,它并不会复制原始数据(可以通过span修改数据,因为内部保存容器数据指针),所以作为参数传递时更加快捷。

两个比较重要的成员函数:

  • data():返回原始容器或数组的指针,可以用这个指针来修改数据
  • `subspan(std::size_t Offset,

    std::size_t Count)`:从span基础上再创建新的子视图

示例如下:

  1. void print(span<int> values)
  2. {
  3. for (const auto &value : values)
  4. {
  5. cout << value << " ";
  6. }
  7. cout << endl;
  8. }
  9. int main()
  10. {
  11. vector v{11, 22, 33, 44, 55, 66};
  12. //直接传vector,因隐式转换为全范围的span
  13. print(v);
  14. //创建全范围span作为参数
  15. span mySpan{v};
  16. print(mySpan);
  17. //从全范围span创建子span
  18. span subspan{mySpan.subspan(2, 3)};
  19. print(subspan);
  20. //从vector创建span,因为第一个参数是指针,所以需要调用data()
  21. print({v.data() + 2, 3});
  22. //从array创建span
  23. array<int, 5> arr{5, 4, 3, 2, 1};
  24. print(arr);
  25. print({arr.data() + 2, 3});
  26. //从C数组创建span
  27. int carr[]{9, 8, 7, 6, 5};
  28. print(carr); // The entire C-style array.
  29. print({carr + 2, 3}); // A subview of the C-style array.
  30. }