C++ 拷貝構造


特殊構造函數

類型轉換構造

用從不同類型的對象來構造對象

Complex(double real); //用實數來構造複數類

拷貝構造

用相同類型的對象來構造對象

Complex(Complex const&that); //用另一個複數來構造複數

注意:如果一個類沒有定義拷貝構造函數,那麼編譯器會提供一個默認拷貝構造函數,默認是public

類型轉換構造和拷貝構造示例

定義一個複數類Complex

<code> //Complex.h
#pragma once
#include<iostream>
using namespace std;
class Complex
{
double m_real; //實部
double m_vir; //虛部
public:
Complex(); //無參構造

/*explicit*/ Complex(double real);//類型轉換構造 explicit 防止類型隱式轉換

//不提供拷貝構造函數 編譯器提供一個默認的拷貝構造函數
Complex(Complex const&that); //拷貝構造
void printf()const;
};
/<iostream>/<code>

實現複數類Complex

<code> //Complex.cpp
#include "Complex.h"
Complex::Complex()
{
m_real = 0;
m_vir = 0;
cout << "無參構造" << endl;
}
Complex::Complex(double real)
{
m_real = real;
m_vir = 0;
cout << "類型轉換構造" << endl;
}
Complex::Complex(Complex const & that)
{
this->m_real = that.m_real;
this->m_vir = that.m_vir;
cout << "拷貝構造" << endl;
}
void Complex::printf() const
{
cout << m_real << "+" << m_vir << "i" << endl;
}
/<code>

使用這個類

<code> //main.c
#include"Complex.h"
int main()
{
/***無參構造***/

Complex var;
var.printf();
/***類型轉換構造***/
Complex var_1 = 5; //隱式將int 換成 Complex 因為Complex提供了單參構造 加上 explicit 防止類型隱式轉換
var_1.printf();
/***拷貝構造***/
Complex var_3(var_1);
Complex var_2 = var_1;
var_2.printf();
/***堆區拷貝構造***/
Complex* var_4 = new Complex(var_1);
delete var_4;
cin.get();
return 0;
}
//打印結果
無參構造
0+0i
類型轉換構造
5+0i
拷貝構造
拷貝構造
5+0i
拷貝構造
/<code>

explicit

防止類型隱式轉換

深拷貝和淺拷貝

淺拷貝----複製地址

對內存地址的複製,讓目標指針和源指針指向同塊內存


通過其中一個指針去釋放內存,其他指向改內存的指針會成為野指針


C++ 拷貝構造

深拷貝----複製內存

對拷貝對象的內存進行復制l拷貝結束之後,兩個對象存的值相同,內存地址不同
l兩個對象互不影響,互不干涉


C++ 拷貝構造

作者:夢凡
鏈接:https://zhuanlan.zhihu.com/p/114332138
來源:知乎
著作權歸作者所有。商業轉載請聯繫作者獲得授權,非商業轉載請註明出處。

何時需要自定義拷貝構造函數

如果類帶有指針變量,並有動態內存分配,則它必須自定義一個拷貝構造函數。

深淺拷貝示例程序

定義一個男朋友類和一個遊戲結構體

<code> //BoyFriend.h
#pragma once
#include<iostream>
#include<string>
using namespace std;
struct game //遊戲類
{
char m_name[10]; //遊戲暱稱
int m_grade; //等級
game(char* name="",int grade=0)
{
strcpy(m_name, name);
m_grade = grade;
}
};
class BoyFriend
{
string m_name;

game* m_account; //一個game類型指針
public:
BoyFriend(string name);
BoyFriend(const BoyFriend& that);
void introduce() const;
~BoyFriend();
};
/<string>/<iostream>/<code>

實現男朋友類

<code> //BoyFriend.cpp
#include "BoyFriend.h"
BoyFriend::BoyFriend(string name)
{
m_name = name;
m_account = new game("馬化騰",201);
}
BoyFriend::BoyFriend(const BoyFriend & that)
{
this->m_name = that.m_name;
#if 0
//淺拷貝 拷貝地址 系統默認的拷貝構造沒有權限分配堆區內存 默認構造函數是淺拷貝
this->m_account = that.m_account;
#endif
#if 1
//深拷貝 拷貝內存 類帶有指針變量,並有動態內存分配,則它必須有一個拷貝構造函數
//1.分配新資源
this->m_account = new game;
//2.拷貝新資源
memcpy(this->m_account, //拷貝的目標內存首地址
that.m_account, //拷貝的源內存首地址
sizeof(game)); //拷貝字節大小
#endif
cout << "拷貝構造" << endl;
}
void BoyFriend::introduce() const
{

cout << "我叫" << m_name <m_name<< ",遊戲賬號等級是" << m_account->m_grade << endl;
}
BoyFriend::~BoyFriend()
{
if (m_account)
{
delete m_account;
m_account = NULL;
}
cout << "析構" << endl;
}
/<code>

使用男朋友類

<code> //main.c
#include"BoyFriend.h"
int main()
{
BoyFriend* boy = new BoyFriend("夢凡");
boy->introduce();

BoyFriend* boy2 = new BoyFriend(*boy); //拷貝構造
boy2->introduce();

delete boy;
boy = NULL;
delete boy2;
boy2 = NULL;
return 0;
}
//打印結果
我叫夢凡,遊戲賬號暱稱是馬化騰,遊戲賬號等級是201
拷貝構造
我叫夢凡,遊戲賬號暱稱是馬化騰,遊戲賬號等級是201
析構
析構/<code>


關注我:帶你遨遊代碼的世界~

獲取更多:私信 “資料” 獲取


分享到:


相關文章: