題目如下:問下列**的列印結果為0嗎?
#include
<
stdlib.h
>
#include
<
iostream
>
using
namespace
std;
struct
clscls()
};int
main()
列印結果是不定的,不一定為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)
可見沒有分配新的記憶體。
正確的方式:
struct
clscls()};
另: 若構造函式呼叫自身,則會出現無限遞迴呼叫,是不允許的
from:
C 一道題搞定C 構造析構的呼叫
include using namespace std class csample char ch1,ch2 public friend void set csample s,char c1,char c2 csample char a,char b ch1 a ch2 b cout csample...
一道有趣的構造題
題意 以下是三道證明題,均在平面上進行討論。以下 x0 y0 x1 y1 x 0,y 0 x 1,y 1 x0 y 0 x1 y1 表示一條從 x0 y0 x 0,y 0 x0 y 0 到 x1 y1 x 1,y 1 x1 y 1 的直線。其中,一條直線與乙個點集合相交表示這條直線上存在乙個點,這個...
C 中構造函式呼叫建構函式
include include using namespace std struct cls cls int main 列印結果是不定的,不一定為0 奇怪的地方在於建構函式中呼叫了自己的另乙個建構函式 我們知道,當定義乙個物件時,會按順序做2件事情 1 分配好記憶體 非靜態資料成員是未初始化的 2 ...