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;

}

我當時是這樣想的,建構函式就是為物件分配記憶體的過程,其主要目的就是為了對私有變數進行初始化,所以我就想一個物件不能呼叫
兩次建構函式,即使這兩種建構函式是過載過的,像題目中的

  CLS()

    {

        CLS(0);

    }
因為不太確定,回來查了一下,原來我之前的理解雖然沾了點邊,但是還是沒有想到點子上去。
首先在物件沒有動態資源的時候,物件的記憶體分配在建構函式之前,此時建構函式的主要任務就是初始化物件的private成員,記憶體分配在建構函式執行之前,所以建構函式裡呼叫另一種形式的建構函式(帶引數的建構函式),其實編譯器又生成了一個臨時物件,這個臨時物件的
private成員通過其引數得到初始化,但是原來的物件的資料成員並沒有初始化,是個隨機值。看了下面的測試程式碼,你就會明白一切

// 建構函式呼叫建構函式的問題.cpp : 定義控制檯應用程式的入口點。
//
#include "stdafx.h"


#include <iostream>
using namespace std;


class Widget
{
public:
Widget(int n)
{
m_idata = n;
cout<<"有引數的建構函式中的this:"<<this<<endl;
}

Widget()
{

cout<<"無引數的建構函式中的this:"<<this<<endl;
Widget(8888);
}


void print() const
{
cout<<"m_idata is:"<<m_idata<<endl;
}

private:
int m_idata;
};


int _tmain(int argc, _TCHAR* argv[])
{
Widget a;
a.print();
system("pause");
return 0;
}



很明顯在兩個建構函式中分別是兩個物件,而且原物件的private成員是個隨機值,所以我們要儘量避免在建構函式中呼叫另一形式的建構函式,那麼建構函式呼叫自身就可以了嗎?當然不行,這樣會陷入無窮遞迴,有興趣的可以實驗一下

如果實在避免不了建構函式呼叫另一形勢的建構函式時怎麼辦?網上查了下,可以用下面的方法解決,new (this)CLS(8888),
這種方式是在原來的物件上呼叫另一形勢的建構函式,不會生成新的臨時物件。
下面是演示程式碼:
// 建構函式呼叫建構函式的問題.cpp : 定義控制檯應用程式的入口點。
//


#include "stdafx.h"
#include <iostream>
using namespace std;


class Widget
{
public:
Widget(int n)
{
m_idata = n;
cout<<"有引數的建構函式中的this:"<<this<<endl;
}

Widget()
{

cout<<"無引數的建構函式中的this:"<<this<<endl;
new (this)Widget(8888);
}


void print() const
{
cout<<"m_idata is:"<<m_idata<<endl;
}
private:
int m_idata;
};


int _tmain(int argc, _TCHAR* argv[])
{
Widget a;
a.print();
system("pause");
return 0;
}

程式輸出:

這時就沒有哪個臨時物件了,而且private資料成員已被初始化

總結:

     不帶引數的建構函式的實現裡去呼叫帶引數的建構函式時,並沒有完成物件內部的函式呼叫,而是優先選擇了通過帶引數建構函式又構造出了一個新的臨時物件,所以儘量避免在建構函式中呼叫建構函式,不管是建構函式自身還是過載過的建構函式




閱讀(627) | 評論(1) | 轉發(1) | 給主人留下些什麼吧!~~ 15_avatar_small.jpg

fera2013-04-03 12:33:23

new (this)CLS(8888)

學名叫replacement new,跟operator new不一樣

回覆 | 舉報 評論熱議