1. 程式人生 > >【轉】C++在建構函式中可以呼叫另一個建構函式嗎

【轉】C++在建構函式中可以呼叫另一個建構函式嗎

題目如下:問下列程式碼的列印結果為0嗎?

    #include <stdlib.h>  
    #include <iostream>  
    using namespace std;  
      
    struct CLS  
    {  
        int m_i;  
        CLS( int i ) : m_i(i){}  
        CLS()  
        {  
            CLS(0);  
        }  
    };  
    int main()  
    {  
        CLS obj;  
        cout << obj.m_i << endl;  
      
        system("PAUSE");  
        return 0;  
    }  
列印結果是【不定】的,不一定為0

程式碼奇怪的地方在於【建構函式】中呼叫了自己的另一個【建構函式】

當定義一個物件時,會按順序做2件事情:

1)分配好記憶體(非靜態資料成員是未初始化的)
2)呼叫建構函式(建構函式的本意就是初始化非靜態資料成員)

顯然上面程式碼中,CLS obj;這裡已經為obj分配了記憶體,然後呼叫預設建構函式,但是預設建構函式還未執行完,卻呼叫了另一個建構函式,這樣相當於產生了一個匿名的臨時CLS物件,它呼叫CLS(int)建構函式,將這個匿名臨時物件自己的資料成員m_i初始化為0;但是obj的資料成員並沒有得到初始化。於是obj的m_i是未初始化的,因此其值也是不確定的

歸納如下:

1)在c++裡,由於建構函式允許有預設引數,使得這種建構函式呼叫建構函式來重用程式碼的需求大為減少
2)如果僅僅為了一個建構函式重用另一個建構函式的程式碼,那麼完全可以把建構函式中的公共部分抽取出來定義一個成員函式(推薦為private),然後在每個需要這個程式碼的建構函式中呼叫該函式即可
3)偶爾我們還是希望在類的建構函式裡呼叫另一個建構函式,可以按下面方式做:
在建構函式裡呼叫另一個建構函式的關鍵是讓第二個建構函式在第一次分配好的記憶體上執行,而不是分配新的記憶體,這個可以用標準庫的placement new做到:
先看看標準庫中placement new的定義

    inline void *__cdecl operator new(size_t, void *_P)  
    {  
        return (_P);   
    }   
可見沒有分配新的記憶體。

正確的方式:
    struct CLS  
    {  
        int m_i;  
        CLS( int i ) : m_i(i){}  
        CLS()  
        {  
            new (this)CLS(0);  
        }  
    };  

另: 若建構函式呼叫自身,則會出現無限遞迴呼叫,是不允許的。

所以,在實際使用的時候,單純的在建構函式中呼叫其它的建構函式,只是會產生一個臨時的匿名變數。如果僅僅是為了重用程式碼,可以把重用的程式碼封裝成一個新的函式。




相關推薦

C++學習筆記-----在一個建構函式呼叫一個建構函式

在建構函式中呼叫另一個建構函式如果一不注意就會有無限遞迴的危險,而且建構函式的引數的不同也決定了呼叫的不同,所以特意總結了一下哪些形式的呼叫時允許的: 首先假設建構函式呼叫時引數都是外部的變數,而不是一個常量。 第一種,也是C++11支援的一種呼叫方式。在函式的初始化列表中

C++如何在一個建構函式呼叫一個建構函式

http://blog.chinaunix.net/uid-23741326-id-3385581.html 在C++中,一個類的建構函式沒法直接呼叫另一個建構函式,比如: 點選(此處)摺疊或開啟 #ifndef _A_H_ #define _A_H_ #i

C#各個版本的新增特性詳解

members 托管 分隔符 main 數據 logs ttr dot 提高 轉自:http://www.cnblogs.com/knowledgesea/p/6694979.html 序言 自從2000年初期發布以來,c#編程語言不斷的得到改進,使我們能夠更加清晰的編

python ,如何在一個函式呼叫一個函式返回的多個值一個

在一個函式中呼叫另一個函式返回的多個值中的一個 首先,定義了一個函式 。 程式碼如下: def createDataSet(): group = array([[1.0,1.1],[1

C++在建構函式可以呼叫一個建構函式

題目如下:問下列程式碼的列印結果為0嗎? #include <stdlib.h> #include <iostream> using namespace std; struct CLS

C++函式引數傳遞的一級指標和二級指標**

主要內容: 1、一級指標和二級指標 2、函式指標傳遞的例子 3、什麼時候需要傳遞二級指標? 4、二級指標在連結串列中的使用 1、一級指標和二級指標 一級指標:即我們一般說的指標,就是記憶體地址; 二級指標:指向指標的指標,就是

C#的兩把雙刃劍:抽象類和接口

實例 可維護 對象 為什麽不使用 程序 一定的 代碼 方式 索引 轉:http://www.cnblogs.com/djzxjblogs/p/7587735.html 第一次面試的時候, 面試官問我,抽象類和接口的區別。 本人也是,按照面試寶典上的回答,說了一大堆。

C++const在函數名前面和函數後面的區別

const成員函數 調用 參數傳遞 成員 指向 int 區別 ... urn 一、概念   當const在函數名前面的時候修飾的是函數返回值,在函數名後面表示是常成員函數,該函數不能修改對象內的任何成員,只能發生讀操作,不能發生寫操作。 二、原理:   我們都知道在調用

C# 在webapi項目配置Swagger

rect static void target 來源 public 圖片 網址 class 以前在做WebAPI調用測試時,一直在使用Fiddler測試工具了,而且這個用起來比較繁瑣,需要各種配置,並且不直觀,還有一點是還得弄明白URL地址和要傳遞的參數,然後才能

AppDomain 詳解二-C#動態加載和卸載DLL

all created 新版本 odin generic reflect 可能 params 詳細 在C++中加載和卸載DLL是一件很容易的事,LoadLibrary和FreeLibrary讓你能夠輕易的在程序中加載DLL,然後在任何地方 卸載。在C#中我們也能使用Asse

C 編譯器優化過程的 Bug

你是 should 有一個 avi return 們的 團隊 ref 似的 一個朋友向我指出一個最近他們發現的 GCC 編譯器優化過程(加上 -O3 選項)裏的 bug,導致他們的產品出現非常詭異的行為。這使我想起以前見過的一個 GCC bug。當時很多人死活認為那種做法是

C#Func與Action的理解

.net ring UNC 簡單 代碼 操作 不必要 返回值 tps 原文地址:https://www.cnblogs.com/ultimateWorld/p/5608122.html Action 與 Func是.NET類庫中增加的內置委托,以便更加簡潔方便的使用委托。最

C#的combobox裏DropDownStyle

csdn https 選項 lis 編輯 mbo art rop tails 源地址:https://blog.csdn.net/cf643487053/article/details/54016822 C#中的combobox控件裏DropDownStyle有三種選項 S

C++虛擬函式

引言 C++中的虛擬函式的作用主要是實現了多型的機制。關於多型,簡而言之就是用父類型別的指標指向其子類的例項,然後通過父類的指標呼叫實際子類的成員函式。這種技術可以讓父類的指標有“多種形態”,這是一種泛型技術。所謂泛型技術,說白了就是試圖使用不變的程式碼來實現可變的演算法。比如:模板技術,RTTI技術,虛擬函

c++的static關鍵字總結

個人總結: static會隱藏全域性變數和全域性函式可見範圍,使其盡在定義檔案中可見; static會改變區域性變數生存週期,在程式中一直存在,而不僅僅在區域性變數定義的函式中; static會改變類的成員變數的生存週期,在程式中一直存在; static會修改函式的使用方

C++堆和棧的理解

一、預備知識—程式的記憶體分配 一個由c/C++編譯的程式佔用的記憶體分為以下幾個部分 1、棧區(stack)— 由編譯器自動分配釋放 ,存放函式的引數值,區域性變數的值等。其操作方式類似於資料結構中的棧。 2、堆區(heap) — 一般由程式設計師分配釋放, 若程式設計

C++異常的堆疊跟蹤

C++異常中的堆疊跟蹤 C++語言的執行時環境是基於棧的環境,堆疊跟蹤(trace stack)就是程式執行時能夠跟蹤並列印所呼叫的函式、變數及返回地址等,C++異常中的堆疊跟蹤就是當程式丟擲異常時,能夠把導致丟擲異常的語句所在的檔名和行號打印出來,以及把呼叫丟擲異常的語句的函

C++類一個建構函式呼叫一個建構函式

class A { int a; int b; int c; public: A(int aa, int bb) : a(aa), b(bb),c(0) { cout << "aa bb" << endl; } A(int aa, in

C++ 常用的STL查詢函式方法

《effective STL》中有句忠告,儘量用演算法替代手寫迴圈;查詢少不了迴圈遍歷,在這裡總結下常用的STL查詢演算法; 查詢有三種,即點線面: 點就是查詢目標為單個元素; 線就是查詢目標為區間; 面就是查詢目標為集合; 針對每個類別的查

C++static用法總結

地址:https://www.cnblogs.com/qiaoconglovelife/p/5323086.html 1.用於區域性變數 C++中區域性變數有三種: (1)auto:此關鍵詞常常省略。auto type a 常常簡寫為type a。 如:int a=auto int