C++淺拷貝(值拷貝)和深拷貝(位拷貝)
阿新 • • 發佈:2019-01-22
一、淺賦值問題
(1)如果類中叧包含簡單資料成員,沒有指向堆的指標, 可以使用編譯器提供的預設複製建構函式
(2)如果類中包含指向堆中資料的指標,淺複製將出現 嚴重問題
①淺複製直接複製兩個物件間的指標成員,導致兩個指標 指向堆中同一坑記憶體區域
② 一個物件的修改將導致另一個物件的修改
③ 一個物件超出作用域,將導致記憶體釋放,使得另一個對 象的指標無效,對其訪問將導致程式異常。
二、編寫自己的賦值建構函式(完成深複製的內容):實現了資源的重新分配
(1)含有指標成員的類,通常需要編寫建構函式和複製 建構函式,同時需要實現相應的複製建構函式,以 及運算子過載
(2)實現“深複製” ,建立物件備仹時,為新物件在堆 中分配自己的記憶體,並將現有值複製到新記憶體中。
Tricycle類舉例:
第一部分:主函式:main.cpp
#include "Tricyle.h" #include "iostream" int main() { Tricycle wichita; Tricycle dallas(wichita); //複製建構函式 wichita.setSpeed(10); std::cout<<"Wichita "; wichita.pedal(); std::cout<<"Dallas "; dallas.pedal(); std::cout<<"Wichita "; wichita.brake(); std::cout<<"Dallas "; dallas.brake(); return 0; }
第二部分,標頭檔案:Tricycle.h
#ifndef TRICYLE_H_INCLUDED #define TRICYLE_H_INCLUDED //defination class class Tricycle { public: Tricycle(); //constructor fun Tricycle(const Tricycle &rsh);//copy constructor fun ~Tricycle(); //disconstructor fun int getSpeed()const{return *speed;} void setSpeed(int newSpeed){*speed = newSpeed;} void pedal(); //速度增加 void brake(); private: int *speed; //在堆中申請了記憶體 }; #endif
第三部分:Tricycle.cpp
#include "Tricyle.h"
#include "iostream"
using namespace std;
Tricycle::Tricycle()
{
speed = new int(5);
}
Tricycle::Tricycle(const Tricycle &rsh)
{
speed = new int ; //申請動態空間,但是並沒有進行初始化
*speed = *rsh.speed; //或者寫成,*speed = rsh.getSpeed();
}
Tricycle::~Tricycle()
{
delete speed;
speed =NULL;
}
//速度增加
void Tricycle::pedal()
{
(*speed)++; //或者setSpeed(getSpeed()+1)
std::cout << "pedaling" << getSpeed()<<'\n';
}
void Tricycle::brake()
{
(*speed)--;
std::cout << "brakeing" << getSpeed()<<'\n';
}
執行結果:
深複製的例子:Person類
#include <iostream>
#include <string>
using namespace std;
class Person
{
public:
Person(); //預設的建構函式
Person(const char *name, int age, char sex); //帶引數建構函式
Person(Person &p); //複製建構函式建構函式
~Person(); //解構函式
void out() //輸出資訊
{cout<<name<<","<<age<<","<<sex<<endl;}
private:
char *name;
char sex;
int age;
};
int main()
{
cout << "***第一種情況,呼叫無參的建構函式"<<endl;;
Person a;
a.out();
cout << "***第二種情況,呼叫含參的建構函式"<<endl;
Person p1("zhangsan",20,'F'); //對建構函式進行初始化
p1.out();
cout << "***第三種情況,複製建構函式"<<endl;
Person p2(p1);
p2.out();
return 0;
}
Person::Person()
{
cout << "\t 呼叫了無引數的建構函式:";
name = new char[10];
strcpy(name,"haoaowei");
sex = 'M';
age = 25;
}
//帶引數建構函式
Person::Person(const char *name, int age, char sex)
{
cout << "\t 呼叫了含引數的建構函式:";
this->name = new char[strlen(name)+1]; //加1是為儲存\0
strcpy(this->name,name);
this->age = age;
this->sex = sex;
}
Person::~Person()
{
cout << "name:"<<name<<"呼叫了解構函式"<< endl;
delete []name;
name = NULL;
}
//複製建構函式
Person::Person(Person &p)
{
cout << "\t 呼叫了複製建構函式:";
name = new char[strlen(p.name)+1];
strcpy(name,p.name);
this->age = p.age;
this->sex = p.sex;
}
執行結果: