1. 程式人生 > >C++淺拷貝(值拷貝)和深拷貝(位拷貝)

C++淺拷貝(值拷貝)和深拷貝(位拷貝)

一、淺賦值問題

(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;
}

執行結果: