C++中的五种构造函数
這里寫目錄標題
- 默認構造函數
- 何時生成默認的構造函數
- 普通構造函數
- 拷貝構造函數
- 何時生成默認的拷貝構造函數
- 拷貝構造函數調用的時機
- 轉換構造函數
- 移動構造函數
C++中的構造函數可以分為5類:默認構造函數、普通構造函數、拷貝構造函數、轉換構造函數、移動構造函數。
默認構造函數
未提供顯式初始值時,用來創建對象的構造函數。以Student類為例,默認構造函數的原型為
Student();//沒有參數 Student(int num=0;int age=0);//所有參數均有默認值何時生成默認的構造函數
當一個類沒有構造函數時,如果滿足以下四個條件其中之一,則編譯器會為該類自動生成一個默認的構造函數:
普通構造函數
C++用于構建類的新對象時需要調用的函數
Student(int num,int age);//有參數拷貝構造函數
何時生成默認的拷貝構造函數
當一個類沒有拷貝構造函數時,如果滿足以下四個條件其中之一,則編譯器會為該類自動生成一個默認的拷貝構造函數:
需要注意的是,默認的拷貝構造函數實現的是淺拷貝。
拷貝構造函數調用的時機
拷貝構造函數在以下三種情況下會被調用。
1).當用一個對象去初始化同類的另一個對象時,會引發復制構造函數被調用。例如,下面的兩條語句都會引發復制構造函數的調用,用以初始化 c2。
Complex c2(c1); Complex c2 = c1;這兩條語句是等價的。
注意,第二條語句是初始化語句,不是賦值語句。賦值語句的等號左邊是一個早已有定義的變量,賦值語句不會引發復制構造函數的調用。例如:
Complex c1, c2; c1=c2;這條語句不會引發復制構造函數的調用,因為 c1 早已生成,已經初始化過了。
2).如果函數 F 的參數是類 A 的對象,那么當 F 被調用時,類 A 的復制構造函數將被調用。換句話說,作為形參的類A的對象,是用復制構造函數初始化的,而且調用復制構造函數時的參數,就是調用函數時所給的實參。
#include<iostream> using namespace std; class A{ public:A(){};A(A & a){cout<<"Copy constructor called"<<endl;} }; void Func(A a){ } int main(){A a;Func(a);return 0; }程序的輸出結果為:
Copy constructor called這是因為 Func 函數的形參 a 在初始化時調用了復制構造函數。
前面說過,函數的形參的值等于函數調用時對應的實參,現在可以知道這不一定是正確的。如果形參是一個對象,那么形參的值是否等于實參,取決于該對象所屬的類的復制構造函數是如何實現的。例如上面的例子,Func 函數的形參 a 的值在進入函數時是隨機的,未必等于實參,因為復制構造函數沒有做復制的工作。
以對象作為函數的形參,在函數被調用時,生成的形參要用復制構造函數初始化,這會帶來時間上的開銷。如果用對象的引用而不是對象作為形參,就沒有這個問題了。但是以引用作為形參有一定的風險,因為這種情況下如果形參的值發生改變,實參的值也會跟著改變。
如果要確保實參的值不會改變,又希望避免復制構造函數帶來的開銷,解決辦法就是將形參聲明為對象的 const 引用。例如:
void Function(const Complex & c) {... }3). 如果函數的返冋值是類 A 的對象,則函數返冋時,類 A 的復制構造函數被調用。換言之,作為函數返回值的對象是用復制構造函數初始化 的,而調用復制構造函數時的實參,就是 return 語句所返回的對象。例如下面的程序:
#include<iostream> using namespace std; class A { public:int v;A(int n) { v = n; };A(const A & a) {v = a.v;cout << "Copy constructor called" << endl;} }; A Func() {A a(4);return a; } int main() {cout << Func().v << endl;return 0; }程序的輸出結果是:
Copy constructor called 4轉換構造函數
一個構造函數接收一個不同于其類類型的形參,可以視為將其形參轉換成類的一個對象。像這樣的構造函數稱為轉換構造函數。在 C++ string 類中可以找到使用轉換構造函數的實用示例。string 類提供一個將 C 字符串轉換為 string 的轉換構造函數
class string {//僅顯示轉換構造函數public:string(char *);//形參時其他類型變量,且只有一個形參 };移動構造函數
所謂移動語義,指的就是以移動而非深拷貝的方式初始化含有指針成員的類對象。簡單的理解,移動語義指的就是將其他對象(通常是臨時對象)擁有的內存資源“移為已用”。事實上,對于程序執行過程中產生的臨時對象,往往只用于傳遞數據(沒有其它的用處),并且會很快會被銷毀。因此在使用臨時對象初始化新對象時,我們可以將其包含的指針成員指向的內存資源直接移給新對象所有,無需再新拷貝一份,這大大提高了初始化的執行效率。
#include <cstring>using namespace std;class Str{public:char *str;Str(Str &&s)//移動構造函數{}~Str(){} };總結
以上是生活随笔為你收集整理的C++中的五种构造函数的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 判断用户首次登录的两种方式
- 下一篇: C++笔试面试题 从网上整理的,带答案