实验三

任务一:

 

任务1代码:

 1 #pragma once
 2 
 3 #include <iostream>
 4 #include <string>
 5 
 6 class Button {
 7 public:
 8     Button(const std::string& label_);
 9     const std::string& get_label() const;
10     void click();
11 
12 private:
13     std::string label;
14 };
15 
16 Button::Button(const std::string& label_) : label{ label_ } {
17 }
18 
19 inline const std::string& Button::get_label() const {
20     return label;
21 }
22 
23 inline void Button::click() {
24     std::cout << "Button '" << label << "' clicked\n";
25 }

 1 #pragma once
 2 
 3 #include <iostream>
 4 #include <vector>
 5 #include <algorithm>
 6 #include "button.hpp"
 7 
 8 // 窗口类
 9 class Window {
10 public:
11     Window(const std::string& title_);
12     void display() const;
13     void close();
14     void add_button(const std::string& label);
15     void click_button(const std::string& label);
16 
17 private:
18     bool has_button(const std::string& label) const;
19 
20 private:
21     std::string title;
22     std::vector<Button> buttons;
23 };
24 
25 Window::Window(const std::string& title_) : title{ title_ } {
26     buttons.push_back(Button("close"));
27 }
28 
29 inline void Window::display() const {
30     std::string s(40, '*');
31     std::cout << s << std::endl;
32     std::cout << "window : " << title << std::endl;
33     int cnt = 0;
34     for (const auto& button : buttons)
35         std::cout << ++cnt << ". " << button.get_label() << std::endl;
36     std::cout << s << std::endl;
37 }
38 
39 inline void Window::close() {
40     std::cout << "close window '" << title << "'" << std::endl;
41     click_button("close");
42 }
43 
44 inline bool Window::has_button(const std::string& label) const {
45     for (const auto& button : buttons)
46         if (button.get_label() == label)
47             return true;
48 
49     return false;
50 }
51 
52 inline void Window::add_button(const std::string& label) {
53     if (has_button(label))
54         std::cout << "button " << label << " already exists!\n";
55     else
56         buttons.push_back(Button(label));
57 }
58 
59 inline void Window::click_button(const std::string& label) {
60     for (auto& button : buttons)
61         if (button.get_label() == label) {
62             button.click();
63             return;
64         }
65 
66     std::cout << "no button: " << label << std::endl;
67 }
 1 #include "window.hpp"
 2 #include <iostream>
 3 void test() {
 4     Window w("Demo");
 5     w.add_button("add");
 6     w.add_button("remove");
 7     w.add_button("modify");
 8     w.add_button("add");
 9     w.display();
10     w.close();
11 }
12 int main() {
13     std::cout << "用组合类模拟简单GUI:\n";
14     test();
15 }

 

任务1截图:

屏幕截图 2025-11-24 222433

 

问题:

1.window和Button是组合关系,因为Window通过add_button能够创建Button对象,存储在Window的std::vector<Button>容器中

2.优点:用户在添加按钮前可以查看这个按钮是否存在,满足了用户的潜在需求。

   缺点:后来如果要修改has_button的内部实现,会导致所有依赖该公有接口的代码失效,维护成本大。

   判断函数应为public还是private首先要判断该函数是否是用户直接需要的功能,若是则应该设为public,再判断这个函数是否仅为内部实现细节,如果是的话应该设为private,以便于后续修改/

3.接口1:const std::string& get_lable() const; 接口2:const std::string get_label() const相比较:

   在性能方面,接口1引用成员变量,无需进行拷贝,没有拷贝开销,性能更好

   在安全方面,接口2返回副本,不会影响内部的状态,而接口1如果原始对象被修改会有风险,所以接口2的安全性更高

4.运行结果一致,两者的差别在push_back(Button(xxx))先创建临时对象Button(xxx),再调用拷贝,而emplace_back(xxx)会直接调用Button(xxx) 在容器尾部构造对象,无需临时对象

 

 任务二:

 

任务2代码:

 1 #include <iostream>
 2 #include <vector>
 3 
 4 void test1();
 5 void test2();
 6 void output1(const std::vector<int>& v);
 7 void output2(const std::vector<int>& v);
 8 void output3(const std::vector<std::vector<int>>& v);
 9 
10 int main() {
11     std::cout << "深复制验证1: 标准库vector<int>\n";
12     test1();
13 
14     std::cout << "\n深复制验证2: 标准库vector<int>嵌套使用\n";
15     test2();
16 }
17 
18 void test1() {
19     std::vector<int> v1(5, 42);
20     const std::vector<int> v2(v1);
21 
22     std::cout << "**********拷贝构造后**********\n";
23     std::cout << "v1: "; output1(v1);
24     std::cout << "v2: "; output1(v2);
25 
26     v1.at(0) = -1;
27 
28     std::cout << "**********修改v1[0]后**********\n";
29     std::cout << "v1: "; output1(v1);
30     std::cout << "v2: "; output1(v2);
31 }
32 
33 void test2() {
34     std::vector<std::vector<int>> v1{ {1, 2, 3}, {4, 5, 6, 7} };
35     const std::vector<std::vector<int>> v2(v1);
36 
37     std::cout << "**********拷贝构造后**********\n";
38     std::cout << "v1: "; output3(v1);
39     std::cout << "v2: "; output3(v2);
40 
41     v1.at(0).push_back(-1);
42 
43     std::cout << "**********修改v1[0]后**********\n";
44     std::cout << "v1: \n";  output3(v1);
45     std::cout << "v2: \n";  output3(v2);
46 }
47 
48 // 使用xx.at()+循环输出vector<int>数据项
49 void output1(const std::vector<int>& v) {
50     if (v.size() == 0) {
51         std::cout << '\n';
52         return;
53     }
54 
55     std::cout << v.at(0);
56     for (auto i = 1; i < v.size(); ++i)
57         std::cout << ", " << v.at(i);
58     std::cout << '\n';
59 }
60 
61 // 使用迭代器+循环输出vector<int>数据项
62 void output2(const std::vector<int>& v) {
63     if (v.size() == 0) {
64         std::cout << '\n';
65         return;
66     }
67 
68     auto it = v.begin();
69     std::cout << *it;
70 
71     for (it = v.begin() + 1; it != v.end(); ++it)
72         std::cout << ", " << *it;
73     std::cout << '\n';
74 }
75 
76 // 使用auto for分行输出vector<vector<int>>数据项
77 void output3(const std::vector<std::vector<int>>& v) {
78     if (v.size() == 0) {
79         std::cout << '\n';
80         return;
81     }
82 
83     for (auto& i : v)
84         output2(i);
85 }

 

任务2截图:

屏幕截图 2025-11-24 225545

 

问题:

1.std::vector<int> v1(5, 42)完成了带参数的普通构造,const std::vector<int> v2(v1)完成了拷贝构造。v1和v2都构造了5个值为42的数据项

2.v1.size() = 2,v2.size() = 2,v1[0].size() = 3

3.能实现同等效果,区别是v1.at(0)会进行边界检查,安全性更高

4.能输出-1,v1.at(0)返回v1第一个内层vector的引用,通过该引用调用push_back(-1),在数组末尾中添加了元素-1,而r.size()-1就是指这个新加的元素,所以能输出-1.

   内存优势:避免了拷贝开销,值接收会拷贝整个内层vector,产生额外内存开销

   内存限制:通过const &绑定的对象不可修改,仅能调用

5.复制构造函数复制了所有元素的实体,实现的是深复制

    当 v是vector<int> 时,v.at(0)返回值类型是int &,

    当v是const vector<int>时,v.at(0)返回值类型const int&

    at()必须提供const重载版本,因为const 对象只能调用 const 成员函数,返回值也需是 const 类型。

 

 任务三:

 

任务3代码:

  1 #pragma once
  2 
  3 #include <iostream>
  4 
  5 // 动态int数组对象类
  6 class vectorInt {
  7 public:
  8     vectorInt();
  9     vectorInt(int n_);
 10     vectorInt(int n_, int value);
 11     vectorInt(const vectorInt& vi);
 12     ~vectorInt();
 13 
 14     int size() const;
 15     int& at(int index);
 16     const int& at(int index) const;
 17     vectorInt& assign(const vectorInt& vi);
 18 
 19     int* begin();
 20     int* end();
 21     const int* begin() const;
 22     const int* end() const;
 23 
 24 private:
 25     int n;     // 当前数据项个数
 26     int* ptr;  // 数据区
 27 };
 28 
 29 vectorInt::vectorInt() :n{ 0 }, ptr{ nullptr } {
 30 }
 31 
 32 vectorInt::vectorInt(int n_) : n{ n_ }, ptr{ new int[n] } {
 33 }
 34 
 35 vectorInt::vectorInt(int n_, int value) : n{ n_ }, ptr{ new int[n_] } {
 36     for (auto i = 0; i < n; ++i)
 37         ptr[i] = value;
 38 }
 39 
 40 vectorInt::vectorInt(const vectorInt& vi) : n{ vi.n }, ptr{ new int[n] } {
 41     for (auto i = 0; i < n; ++i)
 42         ptr[i] = vi.ptr[i];
 43 }
 44 
 45 vectorInt::~vectorInt() {
 46     delete[] ptr;
 47 }
 48 
 49 int vectorInt::size() const {
 50     return n;
 51 }
 52 
 53 const int& vectorInt::at(int index) const {
 54     if (index < 0 || index >= n) {
 55         std::cerr << "IndexError: index out of range\n";
 56         std::exit(1);
 57     }
 58 
 59     return ptr[index];
 60 }
 61 
 62 int& vectorInt::at(int index) {
 63     if (index < 0 || index >= n) {
 64         std::cerr << "IndexError: index out of range\n";
 65         std::exit(1);
 66     }
 67 
 68     return ptr[index];
 69 }
 70 
 71 vectorInt& vectorInt::assign(const vectorInt& vi) {
 72     if (this == &vi)
 73         return *this;
 74 
 75     int* ptr_tmp;
 76     ptr_tmp = new int[vi.n];
 77     for (int i = 0; i < vi.n; ++i)
 78         ptr_tmp[i] = vi.ptr[i];
 79 
 80     delete[] ptr;
 81     n = vi.n;
 82     ptr = ptr_tmp;
 83     return *this;
 84 }
 85 
 86 int* vectorInt::begin() {
 87     return ptr;
 88 }
 89 
 90 int* vectorInt::end() {
 91     return ptr + n;
 92 }
 93 
 94 const int* vectorInt::begin() const {
 95     return ptr;
 96 }
 97 
 98 const int* vectorInt::end() const {
 99     return ptr + n;
100 }
 1 #include "vectorInt.hpp"
 2 #include <iostream>
 3 
 4 void test1();
 5 void test2();
 6 void output1(const vectorInt& vi);
 7 void output2(const vectorInt& vi);
 8 
 9 int main() {
10     std::cout << "测试1: \n";
11     test1();
12 
13     std::cout << "\n测试2: \n";
14     test2();
15 }
16 
17 void test1() {
18     int n;
19     std::cout << "Enter n: ";
20     std::cin >> n;
21 
22     vectorInt x1(n);
23     for (auto i = 0; i < n; ++i)
24         x1.at(i) = (i + 1) * 10;
25     std::cout << "x1: ";  output1(x1);
26 
27     vectorInt x2(n, 42);
28     vectorInt x3(x2);
29     x2.at(0) = -1;
30     std::cout << "x2: ";  output1(x2);
31     std::cout << "x3: ";  output1(x3);
32 }
33 
34 void test2() {
35     const vectorInt  x(5, 42);
36     vectorInt y;
37 
38     y.assign(x);
39 
40     std::cout << "x: ";  output2(x);
41     std::cout << "y: ";  output2(y);
42 }
43 
44 // 使用xx.at()+循环输出vectorInt对象数据项
45 void output1(const vectorInt& vi) {
46     if (vi.size() == 0) {
47         std::cout << '\n';
48         return;
49     }
50 
51     std::cout << vi.at(0);
52     for (auto i = 1; i < vi.size(); ++i)
53         std::cout << ", " << vi.at(i);
54     std::cout << '\n';
55 }
56 
57 // 使用迭代器+循环输出vectorInt对象数据项
58 void output2(const vectorInt& vi) {
59     if (vi.size() == 0) {
60         std::cout << '\n';
61         return;
62     }
63 
64     auto it = vi.begin();
65     std::cout << *it;
66 
67     for (it = vi.begin() + 1; it != vi.end(); ++it)
68         std::cout << ", " << *it;
69     std::cout << '\n';
70 }

 

任务3截图:

屏幕截图 2025-11-25 191741

 

问题:

1.问题:版本2如果发生自赋值(a.assign(a)),delete[]ptr会立即释放a对象的自己的内存,使ptr变成野指针,如果new对象失败会抛出异常,assign函数会终止

2. static_cast<const vectorInt*(this)的作用是将this指针强制转化为const指针,将this指针所指向的对象变成一个const对象,然后调用const版本的at方法

   转换前的返回类型:const int &

   转换后的返回类型 int&

   核心目的:满足非const成员函数的返回类型的要求

3.v1是一个非const对象,会调用非const版本的begin():int *begin();

   v2是一个const对象,会调用const版本的begin():const int *begin() const;

   egin():int *begin()适配场景:对非const对象进行遍历

   const int *begin() const适配场景:对const对象进行遍历,保证对象不被改变

4.可以。

   std::fill_n(ptr,n,value):从ptr指针指向的位置开始,将后n个元素的值填充为value

   std::copy_n(vi.ptr,vi.n,ptr):从地址vi.ptr开始,拷贝vi.n个元素到ptr

   std::copy_n(vi.ptr,vi.n,ptr_tmp):从地址vi.ptr开始,拷贝vi.n个元素到ptr

 

 

任务四:

 

任务4代码:

task4.cpp:

 1 #include <iostream>
 2 #include <cstdlib>
 3 #include "matrix.hpp"
 4 
 5 void test1();
 6 void test2();
 7 void output(const Matrix& m, int row_index);
 8 
 9 int main() {
10     std::cout << "测试1: \n";
11     test1();
12 
13     std::cout << "\n测试2: \n";
14     test2();
15 }
16 
17 void test1() {
18     double x[1000] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
19 
20     int n, m;
21     std::cout << "Enter n and m: ";
22     std::cin >> n >> m;
23 
24     Matrix m1(n, m);    // 创建矩阵对象m1, 大小n×m
25     m1.set(x, n * m);     // 用一维数组x的值按行为矩阵m1赋值
26 
27     Matrix m2(m, n);    // 创建矩阵对象m2, 大小m×n
28     m2.set(x, m * n);     // 用一维数组x的值按行为矩阵m1赋值
29 
30     Matrix m3(n);       // 创建一个n×n方阵对象
31     m3.set(x, n * n);     // 用一维数组x的值按行为矩阵m3赋值
32 
33     std::cout << "矩阵对象m1: \n";   m1.print();
34     std::cout << "矩阵对象m2: \n";   m2.print();
35     std::cout << "矩阵对象m3: \n";   m3.print();
36 }
37 
38 void test2() {
39     Matrix m1(2, 3, -1);
40     const Matrix m2(m1);
41 
42     std::cout << "矩阵对象m1: \n";   m1.print();
43     std::cout << "矩阵对象m2: \n";   m2.print();
44 
45     m1.clear();
46     m1.at(0, 0) = 1;
47 
48     std::cout << "m1更新后: \n";
49     std::cout << "矩阵对象m1第0行 "; output(m1, 0);
50     std::cout << "矩阵对象m2第0行: "; output(m2, 0);
51 }
52 
53 // 输出矩阵对象row_index行所有元素
54 void output(const Matrix& m, int row_index) {
55     if (row_index < 0 || row_index >= m.rows()) {
56         std::cerr << "IndexError: row index out of range\n";
57         exit(1);
58     }
59 
60     std::cout << m.at(row_index, 0);
61     for (int j = 1; j < m.cols(); ++j)
62         std::cout << ", " << m.at(row_index, j);
63     std::cout << '\n';
64 }

Matrix.hpp:

 1 #pragma once
 2 
 3 #include <iostream>
 4 #include <algorithm>
 5 #include <cstdlib>
 6 
 7 // 类Matrix声明
 8 class Matrix {
 9 public:
10     Matrix(int rows_, int cols_, double value = 0); // 构造rows_*cols_矩阵对象, 初值value
11     Matrix(int rows_, double value = 0);    // 构造rows_*rows_方阵对象, 初值value
12     Matrix(const Matrix& x);    // 深复制
13     ~Matrix();
14 
15     void set(const double* pvalue, int size);   // 按行复制pvalue指向的数据,要求size=rows*cols,否则报错退出
16     void clear();   // 矩阵对象数据项置0
17 
18     const double& at(int i, int j) const;   // 返回矩阵对象索引(i,j)对应的数据项const引用(越界则报错后退出)
19     double& at(int i, int j);   // 返回矩阵对象索引(i,j)对应的数据项引用(越界则报错后退出)
20 
21     int rows() const;   // 返回矩阵对象行数
22     int cols() const;   // 返回矩阵对象列数
23 
24     void print() const;   // 按行打印数据
25 
26 private:
27     int n_rows;      // 矩阵对象内元素行数
28     int n_cols;       // 矩阵对象内元素列数
29     double* ptr;    // 数据区
30 };

Matrix.cpp:

  1 #include"matrix.hpp"
  2 #include<iostream>
  3 #include<iomanip>
  4 #include<algorithm>
  5 //普通构造函数
  6 Matrix:: Matrix(int rows_, int cols_, double value):n_rows(rows_),n_cols(cols_)
  7 {
  8     if (rows_ <= 0 || cols_ <= 0)   //边界判断
  9     {
 10         std::cout<<"ERROR";
 11         std::exit(EXIT_FAILURE);
 12     }
 13     else
 14         
 15     {
 16         ptr = new double[rows_ * cols_];         //申请内存
 17         std::fill_n(ptr, cols_ * rows_, value);  //用标准库函数填充数据
 18     }
 19 }
 20 //方阵构造函数
 21 Matrix::Matrix(int rows_, double value ):n_rows(rows_),n_cols(rows_)
 22 {
 23     if (rows_ <= 0)
 24     {
 25         std::cout << "ERROR";
 26         std::exit(EXIT_FAILURE);
 27     }
 28     else
 29     {
 30         ptr = new double[rows_ * rows_];
 31         std::fill_n(ptr, rows_ * rows_, value);
 32     }
 33 }
 34 
 35 //拷贝构造函数(深复制)
 36 Matrix::Matrix(const Matrix& x) :n_rows(x.n_rows), n_cols(x.n_cols)
 37 {
 38     ptr = new double[n_rows * n_cols];
 39     std::copy(x.ptr, x.ptr + (n_rows * n_cols), ptr);
 40 }
 41 
 42 //析构函数
 43 Matrix::~Matrix()
 44 {
 45     delete[] ptr;
 46 }
 47 
 48 
 49 void Matrix::set(const double* pvalue, int size)
 50 {
 51     if (size != n_rows * n_cols)
 52     {
 53         std::cout << "ERROR";
 54         std::exit(EXIT_FAILURE);
 55     }
 56     std::copy(pvalue, pvalue + size, ptr);
 57 }
 58 
 59 void Matrix::clear()
 60 {
 61     if (ptr != nullptr && n_rows > 0 && n_cols > 0)
 62     {
 63         std::fill_n(ptr, n_rows * n_cols, 0.0);
 64     }
 65 }
 66 const double& Matrix::at(int i, int j)const
 67 {
 68     if (i < 0 || i >= n_rows || j < 0 || j >= n_cols)
 69     {
 70         std::cout << "ERROR";
 71         std::exit(EXIT_FAILURE);
 72     }
 73     return ptr[i * n_cols + j];
 74 }
 75 
 76 double& Matrix::at(int i, int j)
 77 {
 78     if (i < 0 || i >= n_rows || j < 0 || j >= n_cols)
 79     {
 80         std::cout << "ERROR";
 81         std::exit(EXIT_FAILURE);
 82         
 83 
 84     }
 85     return ptr[i * n_cols + j];
 86 }
 87 
 88 int Matrix::rows() const
 89 {
 90     return n_rows;
 91 }
 92 
 93 int Matrix::cols() const
 94 {
 95     return n_cols;
 96 }
 97 
 98 void Matrix::print() const {
 99     for (int i = 0;i < n_rows;++i)
100     {
101         for (int j = 0;j < n_cols;++j)
102         {
103             std::cout << ptr[i * n_cols + j]<<",";
104 
105         }
106         std::cout << std::endl;
107     }
108 }

 

任务4截图:

屏幕截图 2025-11-25 221141

 

 

任务五:

任务5代码:

 contact.hpp:

 1 #pragma once
 2 
 3 #include <iostream>
 4 #include <string>
 5 
 6 // 联系人类
 7 class Contact {
 8 public:
 9     Contact(const std::string& name_, const std::string& phone_);
10 
11     const std::string& get_name() const;
12     const std::string& get_phone() const;
13     void display() const;
14 
15 private:
16     std::string name;    // 必填项
17     std::string phone;   // 必填项
18 };
19 
20 Contact::Contact(const std::string& name_, const std::string& phone_) :name{ name_ }, phone{ phone_ } {
21 }
22 
23 const std::string& Contact::get_name() const {
24     return name;
25 }
26 
27 const std::string& Contact::get_phone() const {
28     return phone;
29 }
30 
31 void Contact::display() const {
32     std::cout << name << ", " << phone;
33 }

 

contactBook.hpp:

 1 # pragma  once
 2 
 3 #include <iostream>
 4 #include <string>
 5 #include <vector>
 6 #include <algorithm>
 7 #include "contact.hpp"
 8 
 9 // 通讯录类
10 class ContactBook {
11 public:
12     void add(const std::string& name, const std::string& phone); // 添加联系人
13     void remove(const std::string& name); // 移除联系人
14     void find(const std::string& name) const; // 查找联系人
15     void display() const; // 显示所有联系人
16     size_t size() const;
17 
18 private:
19     int index(const std::string& name) const;  // 返回联系人在contacts内索引,如不存在,返回-1
20     void sort(); // 按姓名字典序升序排序通讯录
21 
22 private:
23     std::vector<Contact> contacts;
24 };
25 
26 void ContactBook::add(const std::string& name, const std::string& phone) {
27     if (index(name) == -1) {
28         contacts.push_back(Contact(name, phone));
29         std::cout << name << " add successfully.\n";
30         sort();
31         return;
32     }
33 
34     std::cout << name << " already exists. fail to add!\n";
35 }
36 
37 void ContactBook::remove(const std::string& name) {
38     int i = index(name);
39 
40     if (i == -1) {
41         std::cout << name << " not found, fail to remove!\n";
42         return;
43     }
44 
45     contacts.erase(contacts.begin() + i);
46     std::cout << name << " remove successfully.\n";
47 }
48 
49 void ContactBook::find(const std::string& name) const {
50     int i = index(name);
51 
52     if (i == -1) {
53         std::cout << name << " not found!\n";
54         return;
55     }
56 
57     contacts[i].display();
58     std::cout << '\n';
59 }
60 
61 void ContactBook::display() const {
62     for (auto& c : contacts) {
63         c.display();
64         std::cout << '\n';
65     }
66 }
67 
68 size_t ContactBook::size() const {
69     return contacts.size();
70 }
71 
72 // 待补足1:int index(const std::string &name) const;实现
73 // 返回联系人在contacts内索引; 如不存在,返回-1
74 int ContactBook::index(const std::string& name)const
75 {
76     for (int i = 0;i < contacts.size();i++)
77     {
78         if (contacts[i].get_name() == name)
79             return i;
80     }
81     return -1;
82 }
83 
84 
85 // 待补足2:void ContactBook::sort();实现
86 // 按姓名字典序升序排序通讯录
87 
88 void ContactBook::sort() {
89     std::sort(contacts.begin(), contacts.end(), [](const Contact& a, const Contact& b) {
90         return a.get_name() < b.get_name();
91         });
92 }

 

task5.cpp:

 1 #include "contactBook.hpp"
 2 
 3 void test() {
 4     ContactBook contactbook;
 5 
 6     std::cout << "1. add contacts\n";
 7     contactbook.add("Bob", "18199357253");
 8     contactbook.add("Alice", "17300886371");
 9     contactbook.add("Linda", "18184538072");
10     contactbook.add("Alice", "17300886371");
11 
12     std::cout << "\n2. display contacts\n";
13     std::cout << "There are " << contactbook.size() << " contacts.\n";
14     contactbook.display();
15 
16     std::cout << "\n3. find contacts\n";
17     contactbook.find("Bob");
18     contactbook.find("David");
19 
20     std::cout << "\n4. remove contact\n";
21     contactbook.remove("Bob");
22     contactbook.remove("David");
23 }
24 
25 int main() {
26     test();
27 }

 

任务5截图:

 

image

 

体会总结:

在实验中,我体会到了cpp标准库函数的方便,加深了对std::fill_n和std::sort的使用

另外在实验四中,代码编译完成后我总是会报错,查询后得知是因为ptr指针悬浮引发的问题,我在边界检查时没有用std::exit(EXIT_FAILURE)终止程序,从而后续调用at和set出现了问题,以后写代码要重视安全性的问题


posted @ 2025-11-25 22:30  杨启霖  阅读(4)  评论(1)    收藏  举报