实验3 类与数组、指针
实验任务1
Point.hpp源码
View Code
View Code
运行测试截图
![]()
回答问题
Q1:对x对象进行更新时,基于 vector<Point> 对象x创建的对象y是否发生变化?
A1:不发生变化。
Q2:标准库模板类vector在复制一个动态数组对象时,实现的是深复制还是浅复制?
A2:深复制。
实验任务2
Point.hpp源码
View Code
vectorPoint.hpp源码
View Code
task2.cpp源码
View Code
运行测试截图
View Code
View Code
View Code
View Code
View Code
View Code
View Code
View Code
View Code
View Code
Point.hpp源码
1 #pragma once 2 3 #include <iostream> 4 using std::cout; 5 using std::endl; 6 7 class Point { 8 public: 9 Point(int x0 = 0, int y0 = 0); 10 ~Point() = default; 11 12 int get_x() const; 13 int get_y() const; 14 void show() const; 15 void move(int new_x, int new_y); 16 17 private: 18 int x, y; 19 }; 20 21 Point::Point(int x0, int y0): x{x0}, y{y0} { 22 } 23 24 int Point::get_x() const { 25 return x; 26 } 27 28 int Point::get_y() const { 29 return y; 30 } 31 32 void Point::show() const { 33 cout << "(" << x << ", " << y << ")" << endl; 34 } 35 36 void Point::move(int new_x, int new_y) { 37 x = new_x; 38 y = new_y; 39 }
task1.cpp源码
1 #include <iostream> 2 #include "point.hpp" 3 #include <vector> 4 5 using std::vector; 6 using std::cin; 7 8 // 输出vector<Point>对象内所有点的坐标 9 void output(const vector<Point> &v) { 10 for(auto &t: v) 11 t.show(); 12 } 13 14 void test() { 15 int n; 16 cout << "输入动态Point数组类对象中元素个数: "; 17 cin >> n; 18 19 vector<Point> x(n); 20 cout << "x对象中所有点坐标信息: " << endl; 21 output(x); 22 23 vector<Point> y(x); // 基于vector<Point>对象x构建对象y 24 cout << "\nx对象中所有点坐标信息: " << endl; 25 output(y); 26 27 cout << "\n更新x对象......" << endl; 28 x.at(0).move(30, 50); // 更新对象x内索引为0的点对象坐标 29 x.push_back(Point(2, 2)); // 向x对象末尾添加一个点对象 30 31 cout << "\nx对象中所有点坐标信息: " << endl; 32 output(x); 33 cout << "\ny对象中所有点坐标信息: " << endl; 34 output(y); 35 } 36 37 int main() { 38 test(); 39 }

回答问题
Q1:对x对象进行更新时,基于 vector<Point> 对象x创建的对象y是否发生变化?
A1:不发生变化。
Q2:标准库模板类vector在复制一个动态数组对象时,实现的是深复制还是浅复制?
A2:深复制。
实验任务2
Point.hpp源码
1 #pragma once 2 3 #include <iostream> 4 using std::cout; 5 using std::endl; 6 7 class Point { 8 public: 9 Point(int x0 = 0, int y0 = 0); 10 ~Point() = default; 11 12 int get_x() const; 13 int get_y() const; 14 void show() const; 15 void move(int new_x, int new_y); 16 17 private: 18 int x, y; 19 }; 20 21 Point::Point(int x0, int y0): x{x0}, y{y0} { 22 } 23 24 int Point::get_x() const { 25 return x; 26 } 27 28 int Point::get_y() const { 29 return y; 30 } 31 32 void Point::show() const { 33 cout << "(" << x << ", " << y << ")" << endl; 34 } 35 36 void Point::move(int new_x, int new_y) { 37 x = new_x; 38 y = new_y; 39 }
1 #pragma once 2 3 #include "point.hpp" 4 #include <cassert> 5 #include <iostream> 6 7 class vectorPoint{ 8 public: 9 vectorPoint(int n); 10 ~vectorPoint(); 11 12 int get_size() const; // 获得当前动态数组内元素个数 13 Point& at(int index); // 返回下标为index的元素引用 14 Point& at(int index) const; // 返回下标为index的元素const引用 15 16 private: 17 int size; // 动态数组的大小 18 Point *ptr; 19 }; 20 21 vectorPoint::vectorPoint(int n) : size{n} { 22 ptr = new Point[n]; 23 } 24 25 vectorPoint::~vectorPoint() { 26 delete[] ptr; 27 } 28 29 int vectorPoint::get_size() const { 30 return size; 31 } 32 33 Point& vectorPoint::at(int index) { 34 assert(index >= 0 && index < size); // 宏,在测试模式下工作。如果不满足条件,则程序终止 35 return ptr[index]; 36 } 37 38 Point& vectorPoint::at(int index) const { 39 assert(index >= 0 && index < size); 40 return ptr[index]; 41 }
1 #include "vectorPoint.hpp" 2 #include <iostream> 3 4 // 输出vectorPoint对象内的所有数据 5 void output(const vectorPoint &v) { 6 for(auto i = 0; i < v.get_size(); ++i) 7 v.at(i).show(); 8 } 9 10 // 测试vectorPoint类:构造对象、复制构造对象 11 void test() { 12 using namespace std; 13 14 int n; 15 cout << "输入vectorPoint对象中元素个数: "; 16 cin >> n; 17 18 vectorPoint x(n); 19 cout << "x对象中所有点坐标信息: " << endl; 20 output(x); 21 22 vectorPoint y(x); 23 cout << "\ny对象中所有点坐标信息: " << endl; 24 output(y); 25 26 cout << "\n更新x对象中点坐标信息......" << endl; 27 x.at(0).move(30, 50); 28 x.at(1).move(-1, -1); 29 30 cout << "x对象中所有点坐标信息: " << endl; 31 output(x); 32 33 cout << "\ny对象中所有点坐标信息: " << endl; 34 output(y); 35 } 36 37 int main() { 38 test(); 39 }

回答问题
Q1:观察更新对象x后,基于 vectorPoint 对象x创建的对象y是否发生变化?
A1:发生变化。
Q2:编译器为vectorPoint类创建的默认复制构造函数,在复制一个动态数组对象时,实现的是深复制还是浅复制?
A2:浅复制。
Q3:在类vectorPoint内部,手动增加的以下复制构造函数声明和定义,实现的是浅复制还是深复制?
A3:浅复制。
实验任务3
Point.hpp源码
1 #pragma once 2 3 #include <iostream> 4 using std::cout; 5 using std::endl; 6 7 class Point { 8 public: 9 Point(int x0 = 0, int y0 = 0); 10 ~Point() = default; 11 12 int get_x() const; 13 int get_y() const; 14 void show() const; 15 void move(int new_x, int new_y); 16 17 private: 18 int x, y; 19 }; 20 21 Point::Point(int x0, int y0): x{x0}, y{y0} { 22 } 23 24 int Point::get_x() const { 25 return x; 26 } 27 28 int Point::get_y() const { 29 return y; 30 } 31 32 void Point::show() const { 33 cout << "(" << x << ", " << y << ")" << endl; 34 } 35 36 void Point::move(int new_x, int new_y) { 37 x = new_x; 38 y = new_y; 39 }
vectorPoint.hpp源码
1 #pragma once 2 3 #include "point.hpp" 4 #include <cassert> 5 #include <iostream> 6 7 class vectorPoint{ 8 public: 9 vectorPoint(int n); 10 vectorPoint(const vectorPoint &vp); 11 ~vectorPoint(); 12 13 int get_size() const; // 获得当前动态数组内元素个数 14 Point& at(int index); // 返回下标为index的元素引用 15 Point& at(int index) const; // 返回下标为index的元素const引用 16 17 private: 18 int size; // 动态数组的大小 19 Point *ptr; 20 }; 21 22 vectorPoint::vectorPoint(int n) : size{n} { 23 ptr = new Point[n]; 24 } 25 26 vectorPoint::vectorPoint(const vectorPoint &vp): size{vp.size}, ptr{new Point[size]} { 27 for(auto i = 0; i < size; ++i) 28 ptr[i] = vp.ptr[i]; 29 } 30 31 vectorPoint::~vectorPoint() { 32 delete[] ptr; 33 } 34 35 int vectorPoint::get_size() const { 36 return size; 37 } 38 39 Point& vectorPoint::at(int index) { 40 assert(index >= 0 && index < size); // 宏,在测试模式下工作。如果不满足条件,则程序终止 41 return ptr[index]; 42 } 43 44 Point& vectorPoint::at(int index) const { 45 assert(index >= 0 && index < size); 46 return ptr[index]; 47 }
task3.cpp源码
1 #include "vectorPoint.hpp" 2 #include <iostream> 3 4 // 输出vectorPoint对象内的所有数据 5 void output(const vectorPoint &v) { 6 for(auto i = 0; i < v.get_size(); ++i) 7 v.at(i).show(); 8 } 9 10 // 测试vectorPoint类:构造对象、复制构造对象 11 void test() { 12 using namespace std; 13 14 int n; 15 cout << "输入vectorPoint对象中元素个数: "; 16 cin >> n; 17 18 vectorPoint x(n); 19 cout << "x对象中所有点坐标信息: " << endl; 20 output(x); 21 22 vectorPoint y(x); 23 cout << "\ny对象中所有点坐标信息: " << endl; 24 output(y); 25 26 cout << "\n更新x对象中点坐标信息......" << endl; 27 x.at(0).move(30, 50); 28 x.at(1).move(-1, -1); 29 30 cout << "x对象中所有点坐标信息: " << endl; 31 output(x); 32 33 cout << "\ny对象中所有点坐标信息: " << endl; 34 output(y); 35 } 36 37 int main() { 38 test(); 39 }
运行测试截图
回答问题
Q1:观察更新对象x后,基于 vectorPoint 对象x创建的对象y是否发生变化?
A1:不发生变化。
Q2:这个vectorPoint 类的实现中,复制构造函数实现的是深复制还是浅复制?
A2:深复制
Q3:基于实验任务2和3,总结当类的成员中包含指针域成员时深复制与浅复制的区别。
A3:当类的成员中包含指针域成员时,默认复制构造函数进行浅复制。浅复制仅复制指针,新指针与原指针指向同一内存区域;深复制复制数据并为之分配单独的内存区域,新指针指向新的内存区域。
实验任务4
task4_1.cpp源码
1 #include <iostream> 2 using namespace std; 3 4 // 函数声明 5 void swap1(int &rx, int &ry); // 引用作为形参 6 void swap2(int *px, int *py); // 指针作为形参 7 void print(int x, int y); // 普通变量作为形参 8 9 // 测试代码 10 void test() { 11 int x = 3, y = 4; 12 13 print(x, y); 14 swap1(x, y); // 函数调用,注意:引用作为形参时,实参形式 15 print(x, y); 16 17 cout << endl; 18 19 x = 3, y = 4; 20 print(x, y); 21 swap2(&x, &y); // 函数调用,注意:指针作为形参时,实参形式 22 print(x, y); 23 } 24 25 int main() { 26 test(); 27 } 28 29 // 函数定义:交换两个变量(引用变量作为形参) 30 void swap1(int &rx, int &ry) { 31 int t; 32 33 t = rx; rx = ry; ry = t; 34 } 35 36 // 函数定义:交换两个变量(指针变量作为形参) 37 void swap2(int *px, int *py) { 38 int t; 39 40 t = *px; *px = *py; *py = t; 41 } 42 43 // 函数定义:输出两个变量(普通变量作为形参) 44 void print(int x, int y) { 45 std::cout << "x = " << x << ", y = " << y << "\n"; 46 }
运行测试截图
task4_2.cpp源码
1 #include <iostream> 2 #include <typeinfo> 3 using namespace std; 4 5 int main() { 6 int a; 7 8 int &ra = a; 9 ra = 4; 10 11 int *pa = &a; 12 *pa = 5; 13 14 // 以十六进制形式输出普通变量a, 引用变量ra,指针变量pa的地址 15 cout << "&a = " << hex << &a << endl; 16 cout << "&ra = " << hex << &ra << endl; 17 cout << "&pa = " << hex << &pa << "\n\n"; 18 19 // 输出普通变量a, 引用变量ra,指针变量pa的值 20 cout << "a = " << a << endl; 21 cout << "ra = " << a << endl; 22 cout << "pa = " << hex << pa << endl; 23 24 // 输出指针变量pa指向的变量的值 25 cout << "*pa = " << *pa << "\n\n"; 26 27 // 输出普通变量a,引用变量ra, 指针变量pa的类型信息 28 cout << "type a: " << typeid(a).name() << endl; 29 cout << "type ra: " << typeid(ra).name() << endl; 30 cout << "type pa: " << typeid(pa).name() << endl; 31 }
运行测试截图
task4_3.cpp源码
1 #include <iostream> 2 #include <vector> 3 4 using namespace std; 5 6 template<typename T> 7 void output(const T &x) { 8 for(auto i: x) 9 std::cout << i << ", "; 10 std::cout << "\b\b \n"; 11 } 12 13 template<typename T> 14 void square1(T &x) { 15 for(auto i: x) // i是普通类型 16 i *= i; 17 } 18 19 template<typename T> 20 void square2(T &x) { 21 for(auto &i: x) // i是引用类型 22 i *= i; 23 } 24 25 void test1() { 26 vector<int> x {1, 2, 3, 4, 5}; 27 28 cout << "动态int型数组对象x内的元素值: "; 29 output(x); 30 31 cout << "调用函数square1()......" << endl; 32 square1(x); 33 34 cout << "动态int型数组对象x内的元素值: "; 35 output(x); 36 } 37 38 void test2() { 39 vector<int> x {1, 2, 3, 4, 5}; 40 41 cout << "动态int型数组对象x内的元素值: "; 42 output(x); 43 44 cout << "调用函数square2()......" << endl; 45 square2(x); 46 47 cout << "动态int型数组对象x内的元素值: "; 48 output(x); 49 } 50 51 int main() { 52 cout << "测试1: " << endl; 53 test1(); 54 55 cout << "\n测试2: " << endl; 56 test2(); 57 }
运行测试截图
回答问题
Q:用文字总结引用类型、指针类型的区别。
A:指针类型:本质是地址,可以独立存在,用于存放数据的地址。可以对指针本身进行操作,也可以通过指针去间接操作数据。引用类型:本质是别名,不能独立存在,依赖于源数据。所有操作同步反馈到源数据上。
实验任务5
vectorInt.hpp源码
1 #include<iostream> 2 class vectorInt { 3 public: 4 vectorInt(int n); 5 vectorInt(int n, int value); 6 vectorInt(const vectorInt &v); 7 ~vectorInt(); 8 int& at(int n); 9 int& at(int n) const; 10 int get_size() const; 11 private: 12 int size; 13 int *s; 14 }; 15 vectorInt::vectorInt(int n) 16 : size{n}, s{new int[n]} { 17 std::cout << "constructor vectorInt(int n) called. \n"; 18 } 19 vectorInt::vectorInt(int n, int value) 20 : size{n}, s{new int[n]} { 21 for (int i = 0; i < n; i++) 22 s[i] = value; 23 std::cout << "constructor vectorInt(int n, int value) called. \n"; 24 } 25 vectorInt::vectorInt(const vectorInt &v) 26 : size{v.size}, s{new int[v.size]} { 27 for (int i = 0; i < size; ++i) 28 s[i] = v.s[i]; 29 std::cout << "copy constructor called. \n"; 30 } 31 vectorInt::~vectorInt() { 32 delete[] s; 33 std::cout << "destructor called" << std::endl; 34 } 35 int vectorInt::get_size() const { 36 return size; 37 } 38 int& vectorInt::at(int n) { 39 return s[n]; 40 } 41 int& vectorInt::at(int n) const { 42 return s[n]; 43 }
task5.cpp源码
1 #include "vectorInt.hpp" 2 #include <iostream> 3 4 using std::cout; 5 using std::cin; 6 using std::endl; 7 8 void output(const vectorInt &vi) { 9 for(auto i = 0; i < vi.get_size(); ++i) 10 cout << vi.at(i) << ", "; 11 cout << "\b\b \n"; 12 } 13 14 void test() { 15 int n; 16 cout << "输入vectorInt对象中元素个数: "; 17 cin >> n; 18 19 vectorInt x1(n); // 构造动态int数组对象x1,包含n个元素,不对元素初始化 20 for(auto i = 0; i < n; ++i) 21 x1.at(i) = i*i; 22 cout << "vectorInt对象x1: "; 23 output(x1); 24 25 vectorInt x2(n, 42); // 构造动态int数组对象x1,包含n个元素,每个元素初始值为42 26 cout << "vectorInt对象x2: "; 27 output(x2); 28 vectorInt x3(x2); // 使用x2构造x3 29 cout << "vectorInt对象x3: "; 30 output(x3); 31 32 cout << "更新vectorInt对象x2......\n"; 33 x2.at(0) = 77; 34 x2.at(1) = -999; 35 36 cout << "vectorInt对象x2: "; 37 output(x2); 38 cout << "vectorInt对象x3: "; 39 output(x3); 40 } 41 42 int main() { 43 test(); 44 }
运行测试截图
实验任务6
matrix.hpp源码
1 #pragma once 2 3 #include <iostream> 4 #include <cassert> 5 6 using std::cout; 7 using std::endl; 8 9 // 类Matrix的声明 10 class Matrix { 11 public: 12 Matrix(int n, int m); // 构造函数,构造一个n*m的矩阵 13 Matrix(int n); // 构造函数,构造一个n*n的矩阵 14 Matrix(const Matrix &x); // 复制构造函数, 使用已有的矩阵X构造 15 ~Matrix(); 16 17 void set(const double *pvalue); // 用pvalue指向的连续内存块数据按行为矩阵赋值 18 void set(int i, int j, double value); // 设置矩阵对象索引(i,j)的元素值为value 19 20 double& at(int i, int j) const; // 返回矩阵对象索引(i,j)的元素引用 21 double& at(int i, int j); // 返回矩阵对象索引(i,j)的元素引用 22 23 int get_lines() const; // 返回矩阵对象行数 24 int get_cols() const; // 返回矩阵对象列数 25 26 void print() const; // 按行打印输出矩阵对象元素值 27 28 private: 29 int lines; // 矩阵对象内元素行数 30 int cols; // 矩阵对象内元素列数 31 double *ptr; 32 }; 33 34 // 类Matrix的实现 35 Matrix::Matrix(int n, int m) : lines{n}, cols{m} { 36 ptr = new double[n * m]; 37 } 38 Matrix::Matrix(int n) : lines{n}, cols{n} { 39 ptr = new double[n * n]; 40 } 41 Matrix::Matrix(const Matrix &x) : lines{x.lines}, cols{x.cols} { 42 ptr = new double[x.lines * x.cols]; 43 for (int i = 0; i < lines * cols; i++) 44 ptr[i] = x.ptr[i]; 45 } 46 Matrix::~Matrix() { 47 delete[] ptr; 48 } 49 50 void Matrix::set(const double *pvalue) { 51 for (int i = 0, j = 0; i < lines * cols; i++, j++) 52 ptr[i] = pvalue[j]; 53 } 54 void Matrix::set(int i, int j, double value) { 55 ptr[i * lines + j] = value; 56 } 57 58 double& Matrix::at(int i, int j) const { 59 return ptr[i * lines + j]; 60 } 61 double& Matrix::at(int i, int j) { 62 return ptr[i * lines + j]; 63 } 64 65 int Matrix::get_lines() const { 66 return lines; 67 } 68 int Matrix::get_cols() const { 69 return cols; 70 } 71 72 void Matrix::print() const { 73 int s = 0; 74 for (int i = 0; i < lines; i++) { 75 cout << ptr[s]; 76 s++; 77 for (int j = 1; j < cols; j++, s++) 78 cout << ", " << ptr[s]; 79 cout << '\n'; 80 } 81 }
task6.cpp源码
1 #include <iostream> 2 #include "matrix.hpp" 3 4 using namespace std; 5 6 const int N1 = 3; 7 const int N2 = 2; 8 9 // 输出一个矩阵对象中索引为index对应的行的所有元素值 10 void output(const Matrix &m, int index) { 11 for(auto j = 0; j < m.get_cols(); ++j) 12 cout << m.at(index, j) << ", "; 13 cout << "\b\b \n"; 14 } 15 16 void test() { 17 18 19 double x[N1*N2] = {3, 1, 4, 1, 5, 9}; 20 21 Matrix m1(N1, N2); // 创建一个N1×N2矩阵 22 m1.set(x); // 用一维数组x的值按行为矩阵m1赋值 23 cout << "矩阵对象m1: " << endl; 24 m1.print(); // 打印矩阵m1的值 25 cout << "矩阵对象m1第0行是: " << endl; 26 output(m1, 0); 27 cout << endl; 28 29 Matrix m2(N2, N1); 30 m2.set(x); 31 cout << "矩阵对象m2: " << endl; 32 m2.print(); 33 cout << "矩阵对象m2第0行是: " << endl; 34 output(m2, 0); 35 cout << endl; 36 37 Matrix m3(m2); // 用矩阵m2构造新的矩阵m3 38 m3.set(0, 0, 999); // 讲矩阵对象m2索引(0,0)元素设为999 39 cout << "矩阵对象m3:" << endl; 40 m3.print(); 41 cout << endl; 42 43 Matrix m4(2); // 创建一个2*2矩阵对象 44 m4.set(x); // 用一维数组x的值按行为矩阵m4赋值 45 cout << "矩阵对象m4:" << endl; 46 m4.print(); 47 } 48 49 int main() { 50 test(); 51 }
运行测试截图

浙公网安备 33010602011771号