Cpp基礎:Constructor 各類構造函數

Cpp 基礎:Constructor 各類構造函數

簡介

C++ 相較於 Java 來說,對對象(object)的控管能力有更上一層樓了,有基本的構造函數(Constructor)析構函數(Destructor),並且提供 newdelete 關鍵字來管理堆上對象的存活,這比起 Java 的垃圾回收機制(GC)更為可靠,內存回收的時間點更為可控。接下來我們就來講解各式各樣的構造函數吧。

參考

c++:(各种)构造函数的调用方式https://blog.csdn.net/VitaLemon__/article/details/60869721
C++ 类 & 对象-菜鸟教程https://www.runoob.com/cplusplus/cpp-classes-objects.html

正文

我們先列出本篇將要介紹的所有將會用到的構造函數和運算符重載:

class Demo {
public:
    // 無參數構造函數
    Demo();
    // 有參數構造函數
    Demo(int);
    // 拷貝構造函數
    Demo(const Demo&);
    // 賦值運算符重載
    void operator=(const Demo&);
    // 析構函數
    ~Demo();
    // 輸出運算符重載
    friend ostream& operator<<(ostream&, const Demo&);

private:
    int _id;
};

接下來我們將一個一個展示使用的時機

1. 無參數構造函數

首先是無參數構造函數,分別是存活在棧(Stack)上和存活在堆(Heap)上的的對象

Demo::Demo() {
  cout << "no-param constructor(" << _id << ")" << endl;
}
int main() {
// 存活在棧上的對象,main 函數結束後調用析構函數並釋放內存
  Demo demo;
  // Demo demo()
  // 棧上調用無參數構造函數不可寫上圓括號

// 存活在堆上的對象,需要主動調用 delete 釋放內存
  Demo* demo2 = new Demo;
  Demo* demo3 = new Demo();
}
output:
no-param constructor(0)
no-param constructor(0)
no-param constructor(0)
destructor(0)
  • 說明:我們創建了三個 Demo 對象,只有第一個棧上存活的對象在 main 函數出棧後會被回收

需要如下主動調用 delete 關鍵字

delete demo2
delete demo3

2. 有參數構造函數(配合初始化列表)

第二種是調用有參數構造函數,這時候圓括號是必須的

Demo::Demo(int id): _id(id) {
  cout << "param constructor(" << _id << ")" << endl;
}
int main() {
// 棧上的對象
  Demo demo(1);

// 堆上的對象
  Demo* demo2 = new Demo(2);
  // 主動釋放對象內存
  delete demo2;
}
output:
param constructor(1)
param constructor(2)
destructor(2)
destructor(1)

3. 拷貝構造函數

第三個是拷貝構造函數,在初始化對象的時候傳如一個對象作為範本

Demo::Demo(const Demo& other) {
  this->_id = other._id;
  cout << "copy-constructor(" << _id << ")" << endl;
}
int main() {
  // 原對象
  Demo demo(1);
  Demo demo2(2);

// 調用拷貝構造函數
  Demo demo3(demo);
// 初始化表達式,與上面等價
  Demo demo4 = demo2;
}
output:
param constructor(1)
param constructor(2)
copy-constructor(1)
copy-constructor(2)
destructor(2)
destructor(1)
destructor(2)
destructor(1)
  • 說明:這邊需要釐清一件事,Demo demo4 = demo2; 是初始化表達式而不是一般的賦值表達式,所以調用的是拷貝構造函數,下面才是使用賦值表達式

4. 賦值運算符重載(對象賦值)

首先我們要先釐清初始化表達式賦值表達式的差異

// 初始化表達式
int i = 0;

// 賦值表達式
int i;
i = 1;

這樣非常容易搞混的,因此 cpp 提供了一種類似構造函數的表達式,能夠避免誤會

int i(100);
// 等價於
int i = 100;

這在類對象賦值也是一樣的,先上方法定義

void Demo::operator=(const Demo& other) {
  this->_id = other._id;
  cout << "Operator overload =: Demo(" << _id << ")" << endl;
}
int main() {
// 對象初始化
  Demo demo(1);
  Demo demo2(2);
// 賦值表達式
  demo2 = demo;
}
output:
param constructor(1)
param constructor(2)
Operator overload =: Demo(1)
destructor(1)
destructor(1)

5. 析構函數

析構函數(destructor)是在回收內存之前會調用的函數,前面已經在輸出的部份看到析構函數的輸出範例了,先看方法定義

Demo::~Demo() {
  cout << "destructor(" << _id << ")" << endl;
}
int main() {
// 棧上對象
  Demo demo(1);
// 堆上對象需要主動調用 delete 釋放內存
  Demo* demo2 = new Demo(2);
  delete demo2;
}
output:
param constructor(1)
param constructor(2)
destructor(2)
destructor(1)

6. 輸出運算符重載(輸出對象)

最後稍微展示一下自定義類的輸出運算符重載

ostream& operator<<(ostream& out, const Demo& other) {
  out << "Operator overload <<: Demo(" << other._id << ")" << endl;
  return out;
}
int main() {
  Demo demo(0);
  cout << demo;
}
output:
param constructor(0)
Operator overload <<: Demo(0)
destructor(0)

結語

本篇總共講解了四種構造函數:無參數構造函數有參數構造函數拷貝構造函數析構函數,並且演示了拷貝構造函數(copy-constructor)賦值表達式(assign expression)的差異,希望大家對於 C++ 中對象的掌控更上一層樓。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值