章节测验与回顾

章节回顾

  1. 固定长度数组(fixed-size arrays)要求在实例化时即已知长度,且之后不可更改。C 风格数组与 std::array 均属此类;动态数组可在运行时调整大小,std::vector 即为动态数组。

  2. std::array 的长度必须是一个常量表达式;通常以整数字面量、constexpr 变量或无作用域枚举值给出。

  3. std::array 是一个聚合体(aggregate),因此没有构造函数,只能使用聚合初始化。

  4. 只要可行,请将 std::array 声明为 constexpr;若非如此,请优先考虑 std::vector。

  5. 使用类模板实参推导(CTAD)让编译器根据初始值推断 std::array 的元素类型与长度。

  6. std::array 的实现形如:
    template<typename T, std::size_t N> // N 是非类型模板形参
    struct array;

  7. 获取 std::array 长度:
    • 成员函数 size()(返回无符号 size_type)。
    • C++17 非成员函数 std::size()(同上)。
    • C++20 非成员函数 std::ssize()(返回带符号整数,通常为 std::ptrdiff_t)。
    三者均返回 constexpr 值;但若形参为引用,则返回非 constexpr(C++23 P2280 已修正)。

  8. 索引 std::array:
    • operator[] 无边界检查,越界产生未定义行为。
    • at() 运行时检查边界;建议避免,除非预先检查或在编译期检查。
    • std::get(arr) 以非类型模板实参 I 在编译期检查边界。

  9. 传递不同元素类型或长度的 std::array 给函数时,可使用
    template <typename T, std::size_t N> 或 C++20 的 template <typename T, auto N>。

  10. 按值返回 std::array 会复制整个数组;若数组较小且元素拷贝开销低,可接受;否则考虑使用输出参数。

  11. 用聚合初始化 std::array 且元素为结构体、类或数组时,若未显式写出元素类型,需额外一对花括号;这是聚合初始化的特性,标准库其它容器(采用列表构造函数)则无需双层花括号。

  12. C++ 聚合支持花括号省略(brace elision):以标量值初始化,或每个元素显式写出类型时可省略多余花括号。

  13. 不可拥有“引用数组”,但可使用 std::reference_wrapper 数组,其行为类似可修改的左值引用:

    • operator= 可重定向引用目标。
  • std::reference_wrapper<T> 可隐式转换为 T&
  • get() 可显式取得 T&
  • 辅助函数 std::ref()std::cref() 用于快速创建包装对象。
  1. 用 static_assert 确保经 CTAD 得到的 constexpr std::array 拥有正确数量的初始值。

  2. C 风格数组继承自 C,属于核心语言特性,具有专用声明语法:

int a[5]; // 方括号内为长度,类型为 std::size_t 的常量表达式。


16. C 风格数组亦为聚合,可用聚合初始化;若用初始化列表为所有元素赋值,建议省略长度,由编译器推导。  

17. C 风格数组可用 operator[] 索引;下标可为带符号 / 无符号整数或无作用域枚举,因此不存在符号转换带来的索引问题。  

18. C 风格数组可以是 const 或 constexpr。  

19. 获取 C 风格数组长度:  
    • C++17 非成员函数 std::size()(返回 std::size_t)。  
    • C++20 非成员函数 std::ssize()(返回带符号整数)。  

20. 在表达式中,C 风格数组通常隐式转换为指向首元素的指针(数组退化)。  

21. 指针算术允许对指针进行加减、自增、自减,以产生新的地址;ptr + 1 指向内存中下一对象。  

22. 从数组起始索引请使用下标;相对当前元素定位请使用指针算术。  

23. C 风格字符串即元素类型为 char 或 const char 的 C 风格数组,同样会发生退化。  

24. 数组维度指选取元素所需下标数量。  
    • 单维度称一维数组;  
    • 数组的数组称二维数组;  
    • 维度多于一个统称多维数组;  
    • 扁平化(flattening)指将多维数组降维至一维。  

25. C++23 的 std::mdspan 为连续元素序列提供多维数组视图。  

## 测验  

问题 1  
指出以下代码片段中的错误并给出修正方法。  

```cpp
a)  
#include <array>  
#include <iostream>  

int main()  
{  
    std::array arr{ 0, 1, 2, 3 };  

    for (std::size_t count{ 0 }; count <= std::size(arr); ++count)  
    {  
        std::cout << arr[count] << ' ';  
    }  
    std::cout << '\n';  
    return 0;  
}

(答案略)

b)  
#include <iostream>  

void printArray(int array[])  
{  
    for (int element : array) { std::cout << element << ' '; }  
}  

int main()  
{  
    int array[]{ 9, 7, 5, 3, 1 };  
    printArray(array);  
    std::cout << '\n';  
}

(答案略)

c)  
#include <array>  
#include <iostream>  

int main()  
{  
    std::cout << "Enter the number of test scores: ";  
    std::size_t length{};  
    std::cin >> length;  

    std::array<int, length> scores;  
      
}

(答案略)

问题 2
实现“Roscoe 药剂商店”。要求详见原题,分三步完成。
(步骤 1、2、3 的提示与解答略)

问题 3
为纸牌游戏构建卡牌与牌组功能。
(步骤 1–4 的提示与解答略)

问题 4
基于上题代码实现简化版二十一点(Blackjack)。
(步骤 1–3 的提示与解答略)

问题 5
a) 描述如何修改程序以支持 A 既可以当 1 又可当 11。
b) 描述如何修改程序以支持平局(分数相同且未爆牌)。
c) 加分项:将以上两点实现,并展示示例输出。
(答案略)

关注公众号,回复"cpp-tutorial"

可领取价值199元的C++学习资料

公众号二维码

扫描上方二维码或搜索"cpp-tutorial"