CAU程序设计2 class6 指针,深浅copy

对象指针

#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;

}

如上述代码中就定义了对象指针,通过对象指针来访问对象成员

常对象指针

#include <iostream>

using namespace std;

class Point {

public:

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

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

int getY()  { return this->y; }

private:

int x, y;

};


int main() {

Point a(4, 5); //普通对象
Point const b(6,7); //常对象

Point const* pa = &a; //定义常对象指针,用a的地址初始化,a是普通对象,但不能通过常指针对象对其进行修改

Point* pb= & b; //定义常对象指针,用常对象b的地址初始化(所以该句代码会出错)

const Point & rb= b; //定义常引用rb,常对象b的别名,要用常引用来引用常对象,否则报错

cout << pa->getX() << endl;//用指针访问对象成员,该代码会报错,因为pa为常指针,要调用常函数

cout<< a->getY() <<endl;

cout << (*pb)->getY() << endl; //用指针求内容运算符访问对象成员

cout << rb.getX() << endl; //用常引用来访问对象成员

return 0;

}

常对象指针的内容均写到了上述代码中了

new 和 delete 操作符:

new, delete与C语言中的malloc和free做对比,malloc和free不会执行构造函数和析构函数。

注意:上述代码中动态分配和删除对象和对象数组的方式是不一样的

特殊成员函数

析构函数

#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() {
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;
}

在上述代码中指明了析构函数,析构函数用于在构造对象生存周期结束时自动释放资源。delete对象时自动调用析构函数。

默认构造函数:
 

如果程序员自己不定义一个构造函数,程序会提供一个默认构造函数,构造一个数值为空的对象。

拷贝构造函数:

如下图所示:点对象p3是用点对象p2创建的,这里调用了拷贝构造函数

在程序员没有定义拷贝构造函数时,编译器会提供一个默认拷贝构造函数(只能实现数值拷贝),当程序员定义了拷贝构造函数时,编译器会使用程序员定义的拷贝构造函数。

下图是一个点对象的拷贝构造函数。

赋值函数:

如果程序员没有重载操作符=,那么编译器会定义一个默认赋值函数;如果程序员定义了则会优先使用程序员定义的赋值函数。

深拷贝和浅拷贝

浅拷贝

只复制了指针的值,两个指针还是指向同一片内存空间,这种情况下,当使用析构函数回收两个指针资源时,会出现回收同一片空间两次的现象,这是要避免的;另外一个问题是在逻辑上我们是希望构造两个不同的对象的,但此时两个对象使用了同一片内存空间,这就导致修改其中一个对象时很可能会同时修改另一个对象。

默认拷贝函数时浅拷贝!

深拷贝

深拷贝会连同指针指向的那片空间一起拷贝,将指向的内容开辟一个新的空间存放。

动态数组类的实现

下面用一个动态数组类的例子来说明构造函数,析构函数的使用。

#include <iostream>
#include <stdlib.h>
using namespace std;

template <class T>
class DynamicArray{
	private:
		T* array;
		unsigned int mallocSize;
	
	public:
		DynamicArray(unsigned length, const T &content){
			mallocSize = length;
			array = new T[length];
			int i;
			for(i = 0; i < length; i++){
				array[i] = content;
			}
			cout<<endl<< "new T["<<this->mallocSize<<"] malloc "<< this->mallocSize << "*"<<sizeof(T)<<"="<<this->mallocSize *sizeof(T)<<" bytes memory in heap";
		}
		~DynamicArray(){
			delete[] array;
			cout<<endl<< "delete[] array free "<< this->mallocSize << "*"<<sizeof(T)<<"="<<this->mallocSize *sizeof(T)<<" bytes memory in heap";
		}
		unsigned int capacity() const;
		T& operator[](unsigned int i);
};

template <class T>
unsigned int DynamicArray<T>::capacity() const {
	return this->mallocSize;
}

template <class T>
T& DynamicArray<T>::operator[](unsigned int i){
	if(i < 0 || i >= mallocSize){
		exit(0);
	}
	return array[i];
}

在构造动态数组时要注意两个问题:

  1. 内存泄漏:如果进程未被杀死(进程被杀死后,内存会由操作系统自动回收),没有使用析构函数回收在堆区开辟的内存,那么在程序运行中程序所占内存就会越来越大,最终导致程序崩溃,这就是内存泄漏。
  2. 数组访问越界:这个问题在使用静态数组时也会出现,就是用下标访问动态数组时,下标范围超过数组有效范围,这时程序就会访问到内存中程序不该访问到的区域,产生安全隐患。上述程序在下标运算符重载时设置了边界保护,防止这种情况发生。

拷贝构造函数

一个对于深拷贝与浅拷贝的实战:

//在类中该成员函数已声明,这里只展示实现

template <class T>
DynamicArray<T>::DynamicArray(const DynamicArray<T> &x){
	this->mallocSize = x.mallocSize;
	this->array = new T[this->mallocSize];
	int i;
	for(i = 0; i < this->mallocSize; i++){
		this->array[i] = x.array[i];
	} 
	cout<<endl<< "Copy Constructor is called";
}

使用这句代码将可以实现拷贝构造

赋值重载函数:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值