【C++初学】课后作业汇总复习(七) 指针-深浅copy

1、 HugeInt类:构造、+、cout

Description:

32位整数的计算机可以表示整数的范围近似为-20亿到+20亿。在这个范围内操作一般不会出现问题,但是有的应用程序可能需要使用超出上述范围的整数。C++可以满足这个需求,创建功能强大的新的数据类型。

定义一个HugeInt类,使用一个数组存储大整数的每一位。如 short integer[ 40 ]; 即可实现存储位数为40位的整数。暂不考虑负数。请根据主函数为该类:

1)定义两个构造,分别接受int和string类型的参数;当参数为string类型时,可以使用字符串处理函数将string类型转换为数值类型。

2)重载+运算,分别能够实现两个HugeInt对象相加,HugeInt与int相加,HugeInt与string相加。提示,先实现两个HugeInt相加,当HugeInt与int相加时,可以将int通过转换构造函数转换为HugeInt类型,然后调用两个HugeInt相加。HugeInt与string相加亦如此。

3)重载<<运算符。

注意:程序前缀、后缀代码已给出。

Sample Input:

Sample Output:

cpp 复制代码
//StudybarCommentBegin
#include <iostream>
#include <cctype> // isdigit function prototype
#include <cstring> // strlen function prototype
using namespace std;

class HugeInt
{
    friend ostream &operator<<( ostream &, const HugeInt & );
public:
    static const int digits = 30;
    HugeInt( long = 0 ); // conversion/default constructor
    HugeInt( const char * ); // conversion constructor
    
    // addition operator; HugeInt + HugeInt
    HugeInt operator+( const HugeInt & ) const;
    
    // addition operator; HugeInt + int
    HugeInt operator+( int ) const;
    
    // addition operator;
    // HugeInt + string that represents large integer value
    HugeInt operator+( const char * ) const;
    
    int getLength() const;
private:
    short integer[ digits ];
}; // end class HugeInt

//StudybarCommentEnd

// Implementation of HugeInt class
HugeInt::HugeInt(long value) {
    // Initialize all digits to 0
    for (int i = 0; i < digits; i++) {
        integer[i] = 0;
    }
    
    // Store digits in reverse order
    for (int i = digits - 1; value != 0 && i >= 0; i--) {
        integer[i] = value % 10;
        value /= 10;
    }
}

HugeInt::HugeInt(const char *str) {
    // Initialize all digits to 0
    for (int i = 0; i < digits; i++) {
        integer[i] = 0;
    }
    
    int len = strlen(str);
    int j = digits - 1;
    
    // Store digits in reverse order
    for (int i = len - 1; i >= 0 && j >= 0; i--) {
        if (isdigit(str[i])) {
            integer[j--] = str[i] - '0';
        }
    }
}

HugeInt HugeInt::operator+(const HugeInt &op2) const {
    HugeInt temp;
    int carry = 0;
    
    for (int i = digits - 1; i >= 0; i--) {
        temp.integer[i] = integer[i] + op2.integer[i] + carry;
        
        if (temp.integer[i] > 9) {
            temp.integer[i] %= 10;
            carry = 1;
        } else {
            carry = 0;
        }
    }
    
    return temp;
}

HugeInt HugeInt::operator+(int op2) const {
    return *this + HugeInt(op2);
}

HugeInt HugeInt::operator+(const char *op2) const {
    return *this + HugeInt(op2);
}

int HugeInt::getLength() const {
    int i;
    for (i = 0; (i < digits) && (integer[i] == 0); i++)
        ; // skip leading zeros
    
    return (i == digits) ? 1 : (digits - i);
}

ostream &operator<<(ostream &output, const HugeInt &num) {
    int i;
    for (i = 0; (i < HugeInt::digits) && (num.integer[i] == 0); i++)
        ; // skip leading zeros
    
    if (i == HugeInt::digits) {
        output << 0;
    } else {
        for (; i < HugeInt::digits; i++) {
            output << num.integer[i];
        }
    }
    
    return output;
}

//StudybarCommentBegin
int main()
{
    HugeInt n1( 7654321 );
    HugeInt n2( 7891234 );
    HugeInt n3( "99999999999999999999999999999" );
    HugeInt n4( "1" );
    HugeInt result;
    
    cout << "n1 is " << n1 << "\nn2 is " << n2
    << "\nn3 is " << n3 << "\nn4 is " << n4
    << "\nresult is " << result << "\n\n";
    
    
    result = n1 + n2;
    cout << n1 << " + " << n2 << " = " << result << "\n\n";
    
    cout << n3 << " + " << n4 << "\n= " << ( n3 + n4 ) << "\n\n";
    
    result = n1 + 9;
    cout << n1 << " + " << 9 << " = " << result << endl;
    
    result = n2 + "10000";
    cout << n2 << " + " << "10000" << " = " << result << endl;
    return 0;
} // end main

//StudybarCommentEnd

2、对象指针定义形式------代码纠正

对象指针定义形式

类名 *对象指针名;

例:

Point a(5,10);

Piont *ptr;

ptr=&a;

通过指针访问对象成员

对象指针名->成员名

例:ptr->getx() 相当于 (*ptr).getx();

例6-12使用指针来访问Point类的成员

//6_12.cpp

#include

using namespace std;

class Point {

public:

Point(int x = 0, int y = 0) : x(x), y(y) { }

int getX() const { return this->x; }

int getY() const { return y; }

private:

int x, y;

};

int main() {

Point a(4, 5);

Point p1 = &a; //定义对象指针,用a的地址初始化

cout << p1.getX() << endl;//用指针访问对象成员

cout << a->getY() << endl; //用对象名访问对象成员

return 0;

}

本题输出结果

4

5

cpp 复制代码
#include <iostream>
using namespace std;

class Point {
public:
    Point(int x = 0, int y = 0) : x(x), y(y) { }
    int getX() const { return this->x; }
    int getY() const { return y; }
private:
    int x, y;
};

int main() {
    Point a(4, 5);
    Point *p1 = &a; // 定义对象指针,用a的地址初始化
    cout << p1->getX() << endl; // 用指针访问对象成员
    cout << a.getY() << endl; // 用对象名访问对象成员
    return 0;
}

3、动态创建对象举例

动态内存分配

动态申请内存操作符 new

new 类型名T(初始化参数列表)

功能:在程序执行期间,申请用于存放T类型对象的内存空间,并依初值列表赋以初值。

结果值:成功:T类型的指针,指向新分配的内存;失败:抛出异常。

释放内存操作符delete

delete 指针p

功能:释放指针p所指向的内存。p必须是new操作的返回值。

本题给出了前缀,本题程序,应该和下列代码等价!

例6-16 动态创建对象举例

#include

using namespace std;

class Point {

public:

Point() : x(0), y(0) {

cout<<"Default Constructor called."<<endl;

}

Point(int x, int y) : x(x), y(y) {

cout<< "Constructor called."<<endl;

}

~Point() { cout<<"Destructor called."<<endl; }

int getX() const { return x; }

int getY() const { return y; }

void move(int newX, int newY) {

x = newX;

y = newY;

}

private:

int x, y;

};

int main() {

cout << "Step one: " << endl;

Point *ptr1 = new Point; //调用默认构造函数

cout<getX()<<endl; //输出GetX

delete ptr1; //删除对象,自动调用析构函数

cout << "Step two: " << endl;

ptr1 = new Point(1,2);

cout<getX()<<endl; //输出GetX

delete ptr1;

return 0;

}

cpp 复制代码
//StudybarCommentBegin
#include <iostream>
using namespace std;
class Point {
public:
	Point();
	Point(int x, int y);
	~Point();
	int getX() const; 
	int getY() const; 
	void move(int newX, int newY);
private:
	int x, y;
};
//StudybarCommentEnd

Point::Point() : x(0), y(0) {
    cout << "Default Constructor called." << endl;
}

Point::Point(int x, int y) : x(x), y(y) {
    cout << "Constructor called." << endl;
}

Point::~Point() {
    cout << "Destructor called." << endl;
}

int Point::getX() const {
    return x;
}

int Point::getY() const {
    return y;
}

void Point::move(int newX, int newY) {
    x = newX;
    y = newY;
}

int main() {
    cout << "Step one: " << endl;
    Point *ptr1 = new Point; //调用默认构造函数
    cout << ptr1->getX() << endl; //输出GetX
    delete ptr1; //删除对象,自动调用析构函数
    cout << "Step two: " << endl;
    ptr1 = new Point(1,2);
    cout << ptr1->getX() << endl; //输出GetX
    delete ptr1;
    return 0;
}

4、 动态创建对象数组举例

例6-17 动态创建对象数组举例

分配和释放动态数组

分配:new 类型名T [ 数组长度 ]

数组长度可以是任何表达式,在运行时计算

释放:delete[] 数组名p

释放指针p所指向的数组。

p必须是用new分配得到的数组首地址。

例6-17 动态创建对象数组举例

cpp 复制代码
#include<iostream>

using namespace std;

#include <iostream>

using namespace std;

class Point {

public:

Point() : x(0), y(0) {

cout<<"Default Constructor called."<<endl;

}

Point(int x, int y) : x(x), y(y) {

cout<< "Constructor called."<<endl;

}

~Point() { cout<<"Destructor called."<<endl; }

int getX() const { return x; }

int getY() const { return y; }

void move(int newX, int newY) {

x = newX;

y = newY;

}

private:

int x, y;

};

int main() {
Point *ptr = new Point[2]; //创建对象数组
ptr[0].move(5, 10); //通过指针访问数组元素的成员
cout<<ptr[0].getY()<<endl;
ptr[1].move(15, 20); //通过指针访问数组元素的成员
cout<<ptr[1].getY()<<endl;   
cout << "Deleting..." << endl;
delete[] ptr; //删除整个对象数组
return 0;
}

5、浅层复制与深层复制

浅层复制

实现对象间数据元素的一一对应复制。

深层复制

当被复制的对象数据成员是指针类型时,不是复制该指针成员本身,而是将指针所指对象进行复制

例6-21 对象的浅层复制

#include

#include

using namespace std;

class Point {

//类的声明同例6-16

//......

};

class ArrayOfPoints {

//类的声明同例6-18

//......

};

int main() {

int count;

cout << "Please enter the count of points: ";

cin >> count;

ArrayOfPoints pointsArray1(count); //创建对象数组

pointsArray1.element(0).move(5,10);

pointsArray1.element(1).move(15,20);

ArrayOfPoints pointsArray2(pointsArray1); //创建副本

cout << "Copy of pointsArray1:" << endl;

cout << "Point_0 of array2: " << pointsArray2.element(0).getX() << ", "

<< pointsArray2.element(0).getY() << endl;

cout << "Point_1 of array2: " << pointsArray2.element(1).getX() << ", "

<< pointsArray2.element(1).getY() << endl;

pointsArray1.element(0).move(25, 30);

pointsArray1.element(1).move(35, 40);

cout<<"After the moving of pointsArray1:"<<endl;

cout << "Point_0 of array2: " << pointsArray2.element(0).getX() << ", "

<< pointsArray2.element(0).getY() << endl;

cout << "Point_1 of array2: " << pointsArray2.element(1).getX() << ", "

<< pointsArray2.element(1).getY() << endl;

return 0;

}

运行结果如下:

Please enter the number of points:2

Default Constructor called.

Default Constructor called.

Copy of pointsArray1:

Point_0 of array2: 5, 10

Point_1 of array2: 15, 20

After the moving of pointsArray1:

Point_0 of array2: 25, 30

Point_1 of array2: 35, 40

Deleting...

Destructor called.

Destructor called.

Deleting...

接下来程序出现运行错误。

例6-22 对象的深层复制

#include

#include

using namespace std;

class Point { //类的声明同例6-16

};

class ArrayOfPoints {

public:

ArrayOfPoints(const ArrayOfPoints& pointsArray);

//其他成员同例6-18

};

ArrayOfPoints::ArrayOfPoints(const ArrayOfPoints& v) {

size = v.size;

points = new Point[size];

for (int i = 0; i < size; i++)

points[i] = v.points[i];

}

int main() {

//同例6-20

}

程序的运行结果如下:

Please enter the number of points:2

Default Constructor called.

Default Constructor called.

Default Constructor called.

Default Constructor called.

Copy of pointsArray1:

Point_0 of array2: 5, 10

Point_1 of array2: 15, 20

After the moving of pointsArray1:

Point_0 of array2: 5, 10

Point_1 of array2: 15, 20

Deleting...

Destructor called.

Destructor called.

Deleting...

Destructor called.

Destructor called.

cpp 复制代码
#include <iostream>
#include <cassert>
using namespace std;

class Point {
public:
    Point() : x(0), y(0) {
        cout << "Default Constructor called." << endl;
    }
    ~Point() {
        cout << "Destructor called." << endl;
    }
    void move(int newX, int newY) { x = newX; y = newY; }
    int getX() const { return x; }
    int getY() const { return y; }
private:
    int x, y;
};

class ArrayOfPoints {
public:
    ArrayOfPoints(int size) : size(size) {
        points = new Point[size];
    }
    
    // 复制构造函数(深层复制)
    ArrayOfPoints(const ArrayOfPoints& v) {
        size = v.size;
        points = new Point[size];
        for (int i = 0; i < size; i++)
            points[i] = v.points[i];
    }
    
    ~ArrayOfPoints() {
        cout << "Deleting..." << endl;
        delete[] points;
    }
    
    Point& element(int index) {
        assert(index >= 0 && index < size);
        return points[index];
    }
    
private:
    Point* points;
    int size;
};

int main() {
    int count;
    cout << "Please enter the number of points:" << endl;
    cin >> count;
    
    ArrayOfPoints pointsArray1(count); //创建对象数组
    pointsArray1.element(0).move(5, 10);
    pointsArray1.element(1).move(15, 20);
    
    ArrayOfPoints pointsArray2(pointsArray1); //创建副本(深层复制)
    
    cout << "Copy of pointsArray1:" << endl;
    cout << "Point_0 of array2: " << pointsArray2.element(0).getX() << ", " 
         << pointsArray2.element(0).getY() << endl;
    cout << "Point_1 of array2: " << pointsArray2.element(1).getX() << ", " 
         << pointsArray2.element(1).getY() << endl;
    
    pointsArray1.element(0).move(25, 30);
    pointsArray1.element(1).move(35, 40);
    
    cout << "After the moving of pointsArray1:" << endl;
    cout << "Point_0 of array2: " << pointsArray2.element(0).getX() << ", " 
         << pointsArray2.element(0).getY() << endl;
    cout << "Point_1 of array2: " << pointsArray2.element(1).getX() << ", " 
         << pointsArray2.element(1).getY() << endl;
    
    return 0;
}

6、动态数组------基本模板类

本题目有后缀

题目描述:

动态数组,是相对于静态数组而言。静态数组的长度是编程时程序员预先定义好的,在整个程序运行中,数组大小无法改变。

而动态数组则不然,它可以随程序运行的需要而在运行时重新指定大小。

动态数组的内存空间是从堆(heap)上分配(即动态分配)的。是通过执行new(或malloc等函数)操作,而为其分配存储空间。当程序执行到这些语句时,才为其分配。

对于动态数组类所申请的内存,在使用完必须由程序员自己释放,否则严重会引起内存泄露。

所以内存的申请一定要有借有还,才能再借不难,也要注意,不能多还。

已知动态数组模板类的定义如下。

请补充完整

1、构造函数

2、析构函数

3、返回空间大小的 capacity() 函数

4、operator[] 重载

template

class DynamicArray {

private:

T* array; //pointer ,一个T类型的指针

unsigned int mallocSize; //分配空间的大小。

public:

//Constructors

// cout<<endl<< "new T["<mallocSize<<"] malloc "<< this->mallocSize << "*"<<sizeof(T)<<"="<mallocSize *sizeof(T)<<" bytes memory in heap";

DynamicArray(unsigned length, const T &content) ; // mallocSize=length; 设置每个元素的初始内容是 content;

// Destructors

// cout<<endl<< "delete[] array free "<< this->mallocSize << "*"<<sizeof(T)<<"="<mallocSize *sizeof(T)<<" bytes memory in heap";

~DynamicArray();

//return the this->mallocSize

unsigned int capacity() const;

// for the array[i]=someT.

T& operator[](unsigned int i) ;

};

输入一个整数

输出请分析参见下面的用例和程序后缀。

样例输入:

3

样例输出

new T[3] malloc 34=12 bytes memory in heap
new T[3] malloc 3
8=24 bytes memory in heap

capacity:3

-1 -1 -1

-2.1 -2.1 -2.1

0 1 2

0 1.1 2.2

delete[] array free 38=24 bytes memory in heap
delete[] array free 3
4=12 bytes memory in heap

cpp 复制代码
#include <iostream>
using namespace std;

template <typename T>
class DynamicArray {
private:
    T* array; //pointer  ,一个T类型的指针
    unsigned int mallocSize; //分配空间的大小。

public:
    //Constructors 
    // cout<<endl<< "new T["<<this->mallocSize<<"] malloc "<< this->mallocSize << "*"<<sizeof(T)<<"="<<this->mallocSize *sizeof(T)<<" bytes memory in heap";
    DynamicArray(unsigned length, const T &content) {
        mallocSize = length;
        array = new T[length];
        for (unsigned int i = 0; i < length; ++i) {
            array[i] = content;
        }
        cout << "new T[" << mallocSize << "] malloc " << mallocSize << "*" << sizeof(T) << "=" << mallocSize * sizeof(T) << " bytes memory in heap\n";
    }

    // Destructors
    // cout<<endl<< "delete[] array free "<< this->mallocSize << "*"<<sizeof(T)<<"="<<this->mallocSize *sizeof(T)<<" bytes memory in heap";
    ~DynamicArray() {
        cout << endl << "delete[] array free " << mallocSize << "*" << sizeof(T) << "=" << mallocSize * sizeof(T) << " bytes memory in heap";
        delete[] array;
    }

    //return the this->mallocSize
    unsigned int capacity() const {
        return mallocSize;
    }

    // for the array[i]=someT.
    T& operator[](unsigned int i) {
        return array[i];
    }
};
相关推荐
巨可爱熊22 分钟前
高并发内存池(定长内存池基础)
linux·运维·服务器·c++·算法
qq_365911602 小时前
GPT-4、Grok 3与Gemini 2.0 Pro:三大AI模型的语气、风格与能力深度对比
开发语言
码农新猿类3 小时前
服务器本地搭建
linux·网络·c++
Susea&3 小时前
数据结构初阶:队列
c语言·开发语言·数据结构
慕容静漪3 小时前
如何本地安装Python Flask并结合内网穿透实现远程开发
开发语言·后端·golang
ErizJ3 小时前
Golang|锁相关
开发语言·后端·golang
GOTXX3 小时前
【Qt】Qt Creator开发基础:项目创建、界面解析与核心概念入门
开发语言·数据库·c++·qt·图形渲染·图形化界面·qt新手入门
搬砖工程师Cola3 小时前
<C#>在 .NET 开发中,依赖注入, 注册一个接口的多个实现
开发语言·c#·.net
巨龙之路3 小时前
Lua中的元表
java·开发语言·lua
徐行1104 小时前
C++核心机制-this 指针传递与内存布局分析
开发语言·c++