先看示例代碼
點擊查看代碼
#include <iostream>
#include<cstring>
using namespace std;
class Student{
public:
Student(int _age , const char * _name)
{
this->age=_age;
int len=strlen(_name)+1;
char *tep=new char[len];
this->pName=tep;
strcpy(this->pName,_name);
}
~Student(){
delete[]this->pName;
this->pName=nullptr;
}
void showStudent(){
cout<<this->pName<<" "<<this->age<<endl;
}
private:
int age;
char *pName;
};
int main(){
Student s1(20,"zhangsan");
s1.showStudent();
Student s2=s1;
s2.showStudent();
return 1;
}
上面示例代碼中,物件的默認拷貝方式是記憶體資料拷貝,如果物件占用了外部資源,那么就會出現問題了,這里的外部資源
就是在堆上申請的空間存放名字用,
s1,s2兩個物件中的名字指標都是指向了同一塊堆記憶體區域,在結束main函式的是,s2先析構,s2會析構調堆上的記憶體空間,
s1再析構,由于s1物件的pName 指標和s2物件的pName指標指向的是同一塊堆記憶體區域,但是該區域記憶體已經被釋放了,所以遇到了問題
鑒于上面的問題,我們引出了 淺拷貝,深拷貝的問題和解決方法.
Student s2=s1; 會呼叫拷貝建構式(該拷貝建構式可以是系統自動生成的,或者你自己定義一個拷貝建構式)
系統自動生成的拷貝建構式做的是記憶體資料拷貝,所以就出現了上面的問題.因此我們需要定義屬于自己的拷貝建構式
改造代碼如下
點擊查看代碼
class Student2{
public:
Student2(int _age , const char * _name)
{
this->age=_age;
int len=strlen(_name)+1;
char *tep=new char[len];
this->pName=tep;
strcpy(this->pName,_name);
cout<<"執行建構式"<<endl;
}
//自定義拷貝建構式
Student2(const Student2 &_stu2){
this->age=_stu2.age;
int len =strlen(_stu2.getPName())+1;
char *newPName =new char[len];
this->pName=newPName;
strcpy(this->pName,_stu2.getPName());
cout<<"執行拷貝建構式"<<endl;
}
~Student2(){
if(this->pName!=nullptr){
delete[]this->pName;
this->pName=nullptr;
}
}
void showStudent(){
int *p=(int *)this->pName;
cout<<this->pName<<" "<<this->age<<" pName Heap Address ="<<p<<endl;
}
const char * getPName() const{
return this->pName;
}
private:
int age;
char *pName;
};
int main(){
Student2 s1(20,"zhangsan");
s1.showStudent();
Student2 s2=s1;
s2.showStudent();
return 1;
}
上面的代碼還存在一個問題如下,如果在main函式中是下面的代碼
Student2 s1(20,"zhangsan");
Student2 s2(30,"lisi");
s2=s1;
在main函式結束的是同樣會遇到問題,這個時候就引出 賦值函式,我們需要定義自己的賦值函式
在 s2=s1這一段代碼其實是這樣呼叫的
s2.operator=(s1)
在你不定義自己的賦值函式的時候,系統會幫我們生成一個賦值函式,該賦值函式的賦值方式就是記憶體的數值拷貝,這種方式
在Student物件,會有問題,所以我們需要向自定義拷貝構造一樣,定義一個屬于自己的賦值函式
代碼如下
點擊查看代碼
class Student3{
public:
Student3(int _age , const char * _name)
{
this->age=_age;
int len=strlen(_name)+1;
char *tep=new char[len];
this->pName=tep;
strcpy(this->pName,_name);
cout<<"執行建構式"<<endl;
}
//自定義拷貝建構式
Student3(const Student3 & _stu){
this->age=_stu.age;
int len =strlen(_stu.getPName())+1;
char *newPName =new char[len];
this->pName=newPName;
strcpy(this->pName,_stu.getPName());
cout<<"執行拷貝建構式"<<endl;
}
//自定義賦值函式
Student3 & operator= (const Student3 & _stu){
//防止自賦值
if(this==&_stu){return *this;}
//注意: 需要先釋放當前的堆記憶體空間!!
delete []this->pName;
this->age=_stu.age;
int len =strlen(_stu.getPName())+1;
char *newPName =new char[len];
this->pName=newPName;
strcpy(this->pName,_stu.getPName());
cout<<"執行賦值函式"<<endl;
return *this;
}
~Student3(){
if(this->pName!=nullptr){
delete[]this->pName;
this->pName=nullptr;
}
}
void showStudent(){
int *p=(int *)this->pName;
cout<<this->pName<<" "<<this->age<<" pName Heap Address ="<<p<<endl;
}
const char * getPName() const{
return this->pName;
}
private:
int age;
char *pName;
};
int main(){
Student3 s3(20,"zhangsan");
s3.showStudent();
Student3 s4(30,"lisi");
s4=s3;
s4.showStudent();
return 1;
}
運用深拷貝淺拷貝實作String 代碼如下
點擊查看代碼
#include <iostream>
#include <cstring>
using namespace std;
class MyString{
public:
//建構式
MyString(const char * src){
//創建空串
if(src=https://www.cnblogs.com/erichome/p/=nullptr){
this->pchar=new char[1];
this->pchar[0]='\0';
}
else{
int len =strlen(src)+1;
this->pchar=new char[len];
strcpy(this->pchar,src);
}
cout<<"執行建構式, 堆記憶體空間地址"<<(int *)this->pchar <<endl;
}
//拷貝構造
MyString(const MyString & myString){
//重新分配記憶體空間
int len =myString.stringLen()+1;
this->pchar=new char[len];
strcpy(this->pchar,myString.pchar);
cout<<"執行拷貝建構式, 新創建堆記憶體空間地址"<<(int *)this->pchar <<endl;
}
//賦值函式
MyString & operator=(const MyString & myString){
//防止自賦值
if(this==&myString){return *this;}
//釋放現有的堆記憶體空間
delete[]this->pchar;
this->pchar=nullptr;
int len =myString.stringLen()+1;
this->pchar=new char[len];
strcpy(this->pchar,myString.pchar);
cout<<"執行賦值函式, 新創建堆記憶體空間地址"<<(int *)this->pchar <<endl;
return *this;
}
int stringLen() const {
return strlen(this->pchar);
}
//析構
~MyString(){
delete [] this->pchar;
this->pchar=nullptr;
}
void printChar() const{
cout<<this->pchar<<endl;
}
private:
char *pchar;
};
int main(){
MyString s1("abcd");
s1.printChar();
MyString s2=s1;//執行拷貝構造
s2.printChar();
MyString s3("1234");
s3=s1;//執行賦值函式
s3.printChar();
return 1;
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/532503.html
標籤:C++
上一篇:<二>掌握建構式和解構式
下一篇:<四>建構式初始化串列
