嵌入式工程師
3次就業內推,全流程就業服務,行業風口、政策傾斜,新晉熱門高薪不內卷,越老越吃香!0基礎一站式就業完整路徑,搶占先發優勢!
上一小節中,我們介紹了構造函數和析構函數。這一小節,我們來介紹一個特殊的構造函數。
先來看一個例程:
int main(int argc,char **argv)
{
Staff staffA;
Staff staffB = staffA;
return 0;
}
我們先實例化了一個對象 staffA,然后又實例化了一個對象 staffB。希望 staffB 和 staffA 具有相同的內容,或者說希望 staffB 是 staffA 的副本,那么我們一般直接在實例化的時候進行賦值就可以了。
Staff staffB = staffA;
這樣做了之后,C++ 會自動為我們拷貝 staffA 中的成員變量到 staffB 的成員變量中,但是這種自動拷貝機制在某些情況下無法完成我們想要的動作,甚至有可能會出錯。我們來具體看一下。
在 Staff 類中添加一些內容:
Staff.hpp
#include <string>
class Staff
{
public:
Staff(std::string _name, int _age);
~Staff();
public:
std::string name;
int age;
char * mem = nullptr;
};
Staff.cpp
#include "Staff.hpp"
#include <stdio.h>
Staff::Staff(std::string _name, int _age)
{
mem = (char *)malloc(20);
name = _name;
age = _age;
printf("構造函數被調用\n");
}
Staff::~Staff()
{
if(mem != nullptr){
free(mem);
mem = nullptr;
}
printf("析構函數被調用\n");
}
在上面的代碼中,在類中定義了一個指針,在構造函數中,通過 malloc 函數分配了一個 20 字節大小的堆內存,然后將這片堆內存的首地址賦值給了這個指針。在析構函數中,我們將這片堆內存釋放掉。
這個時候,我們再進行一開始的操作:
Staff staffB = staffA;

先來看看 staffA 在實例化之后的內存布局:

mem 指針指向了一片 20 個字節大小的堆內存。
這個時候,再來看看執行了Staff staffB = staffA;之后,staffB 的內存布局會怎么樣:

可以看到,在 C++ 默認的復制模式之下,兩個對象中的 mem 指針指向了同一片內存。因為 C++ 默認的復制模式只會簡單得把成員的值進行復制,面對這個 mem 指針,他只會把指針的值進行拷貝,最后的結果就是 mem 指針指向了同一片內存。
這種拷貝方式,被稱之為淺拷貝。
Staff staffB = staffA;
當我們使用這種方式實例化對象的時候,并不會調用普通構造函數,而是會調用一個特殊的構造函數,被稱之為賦值構造函數或者拷貝構造函數。如果我們沒有寫,那么就會按照淺拷貝的方式來進行復制。一個拷貝構造函數看起來就像下面這樣:
Staff(const Staff & staff);
這個函數中只有一個參數 staff,表示要拷貝的對象,在我們的例子中,就是 staffA。(const 和 & 我們在后續的課程中會具體講解)
那么我們來完整的編寫一下這個函數
Staff.hpp
#include <string>
class Staff
{
public:
Staff(std::string _name, int _age);
Staff(const Staff & staff);
~Staff();
public:
std::string name;
int age;
char * mem = nullptr;
};
Staff.cpp
#include "Staff.hpp"
#include <stdio.h>
Staff::Staff(std::string _name, int _age)
{
mem = (char *)malloc(20);
name = _name;
age = _age;
printf("構造函數被調用\n");
}
Staff::Staff(const Staff & staff)
{
name = staff.name;
age = staff.age;
mem = (char *)malloc(20);
memcpy(mem, staff.mem, 20);
}
Staff::~Staff()
{
if(mem != nullptr){
free(mem);
mem = nullptr;
}
printf("析構函數被調用\n");
}
請驗證,完成請求
由于請求次數過多,請先驗證,完成再次請求
打開微信掃碼自動綁定
綁定后可得到
使用 Ctrl+D 可將課程添加到書簽
舉報