青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

深入探索C++對象模型讀書筆記 (二)

Posted on 2010-03-03 22:23 rikisand 閱讀(1402) 評論(4)  編輯 收藏 引用 所屬分類: C/C++

構造函數語義學

--了解編譯器在構造對象時背著我們干了什么勾當

Default Ctor 在需要的時候被構建出來~

什么需要? 是編譯器需要而不是程序的需要,所以不要期望編譯器生成的Ctor會幫我們把我們的成員變量初始化為零。那是程序的需要,也就是我們程序員的任務····

例如:

      class Foo(public:int val;);

      void foo_bar(){Foo bar; if(bar.val)dosth;} 不要期望編譯器幫我們初始化它為0。只有global變量會初始化為0,初始化val這樣的變量需要我們自己寫代碼的~~

Default Ctor分為trival(沒用的)和non-trival的,下面討論什么時候編譯器需要ctor 也就是有用的ctor,這時候如果我們沒有提供一個默認的default ctor 它會幫我們合成一個的~~

1.帶有Default Ctor 的member class object

很好理解,既然內部成員含有default ctor 那么我們創建新的對象時需要調用它,而我們并木有調用它的函數,編譯器自然會幫我們提供一個。如果我們提供了default ctor ,那么編譯器會在我們提供的函數加入調用必須調用的member class 的default ctor。同樣的在每一個ctor里面都將在用戶寫的代碼之前調用需要調用的default ctor -------看例子:

class Dopey();class Sneezy{public:Sneezy(int val);Sneezy();};class Bashful{public:BashFul();};

class Snow_white{public: Dopey dopey;Sneezy sneezy;Bashful bashful;private:int muble};

如果Snow_white沒有定義default ctor 那么編譯器會創建一個,并在其中依照聲明順序依次調用dopey sneezy bashful的default ctor 然而如果:

Snow_white::Snow_white():sneezy(1024){muble=2045;}

編譯器會擴張為

Snow_white::Snow_white():sneezy(1024){

  dopey.Dopey::Dopey();

  sneezy.Sneezy::Sneezy(1024);

  bashful.Bashful::Bashful();

  /////////   explicit user code

  muble = 2048;

}

2.派生自帶有Default ctor 的 base class

同樣道理如果父類有Default ctor 子類當然要調用,編譯器會為想上面一樣為我們加上

3.含有virtual functions的Class

創建object 時候需要ctor 來設置好vptr

4.帶有virtual base class

virtual base 實現方法各有不同,然而共同點是必須是virtual base class 在其每一個derived class中的位置能夠與執行期準備妥當

X A B C 菱形繼承

void foo(const A*pa){pa->i=1024;}

foo(new A);foo(new C);

知道pa 后 i在對象中的位置并不是固定的,而是在運行時真正確定pa指向什么對象A還是C才能確定的,因此需要設定一個指向基類subobject的指針,所以需要ctor工作了

OK:

1.任何class 如果沒有定義Default ctor 就會被合成一個

2.合成出來的Default ctor 會明確設定每一個data member值

錯的很easy了~

-------------------------------------------------------------------------------

再來看 Copy Ctor:

copy ctor 負責用另一個對象初始化一個對象

operator = 負責用另一個對象給一個對象賦值

直接賦值時,傳參時,返回時可能調用Copy ctor

Default member initialization~~~

也就是memberwise 的initialization

他會把每一個data member (內建的或者派生的)從一個object 拷貝到另一個object中去

如果object允許bitwise的拷貝那么編譯器就不用生成一個nontrival的default copy ctor

什么時候不可以呢~

1 內含一個member object 而后者含有copy constructor (聲明或者合成的)

2  繼承一個base class 后者有copy ctor

3  含有virtual func

4  派生自一個繼承鏈,其中有virtual base class

1和2 中編譯器會把member 或者baseclass copy ctor 調用安插在合成的copy ctor 中

3 中:

如果兩個同樣類型的object賦值時,沒有問題因為他們的vptr相同

但是考慮子類賦值給父類,此時vptr需要更改,那么此時不具有bitwise特性,因此需要編譯器來加入語句正確更新vptr

4中:

每個編譯器都承諾必須讓derived class 中的virtual base class object 在執行期間準備妥當,維護位置完整性是編譯器的責任。bitwise copy 有可能會破壞這個位置所以編譯器需要在自己合成的copy ctor 中作出仲裁

同樣問題發生在繼承體系中子類向父類賦值時,由于對象模型問題,直接bitwise復制可能會導致base class object 的破壞(后面章節會有討論)

--------------------------------------------------------------------------------

程序轉化語義學:

X x0;

void foo(){X x1(x0); X x2=x0; X x3=X(x0);}

轉化:重寫定義,初始化操作會被剝除   copy constructor 調用會被安插

void foo(){ X x1;X x2; X x3;  x1.X::X(x0); x2.X::X(x0); x3.X::X(x0);}

 

參數的初始化:

一種策略導入暫時的object

void foo(X x0);X xx; foo(xx);

轉化:

X _tmp;

_tmp.X::X(x0); foo(_tmp);

foo變成 void foo(X& x0);

另一種是拷貝構建:

把實際參數直接建構造應該在的位置上,函數返回時局部對象的destructor 會執行

也就是說把x0建構在foo 的函數執行的地方

 

返回值的初始化:

X bar(){

    X xx;

    return xx;

}

返回值如何從局部對象xx拷貝而來呢?

一種方法:1.加上額外參數,類型是class object的reference,這個參數用來放置被拷貝建構的返回值 (注意拷貝建構也就是說他被放在應該在的位置,也就是說不是局部變量了)

2.return 指令之前安插一個copy constructor 調用操作 ,以便將傳回的object 內容當做上述參數的初值

so 上面的程序變成了:

void bar(X& _result){

  X xx;

  xx.X::X(); //編譯器產生的default ctor 調用

  _result.X::X(xx);//編譯器產生的copy ctor 調用

  return ;

}

現在編譯器必須轉換bar的調用操作 X xx=bar();轉換成 X xx; bar(xx); // 注意不用copy ctor了直接操作在xx上了 如果編譯器做了優化 這就是named return value 優化

而:

bar.memfunc();//bar()傳回的X 調用成員函數

變成:

X _tmp;  (bar(_tmp),_tmp).memfunc();

同樣道理函數指針 X(*pf)(); 變成 void (*pf)(X&);

使用者的優化:

X bar(const T& y,const T& z){

    X xx;

    通過 y z 計算xx

   return xx;

}

這種情況下要iuxx被memberwise拷貝到編譯器產生的_result中,

如果定義 ctor來利用yz計算xx則:

X bar(const T& y,const T& z){

     return X(y,z);

}

變成:

bar(X& result){

     result . X::X(y,z);

     return;

}

無需copy ctor了

 

編譯器的優化:

如上所述bar中返回了具名數值 named value,因此編譯器有可能自己優化,方法是以result取代named return value

bar(X& result){_result.X::X(); 直接處理result 并不處理變量xx然后復制給result 這樣就優化了}

這個優化的激活需要class提供一個copy ctor~~~~~~

 

Copy ctor 要不要:

如果一個class 符合bitwise的要求那么此時member wise 的拷貝已經高效簡潔 無需加入了

但是如果class需要大量的member wise 初始化操作,如用傳值方式返回objects,如果是這樣提供一個copy ctor 可以激活nRV named return value 優化,這就很合理了

 

成員們的初始化過程:

什么時候必須用初始化列表:

1.初始化一個reference時 2.初始化一個const member 3.調用父類ctor而且有參數時4調用member class ctor 有參數

其他情況呢:

class word{string name;int cnt;public: name=0;cnt=0;}

編譯器可能這么做:

word::word{

    name.String::string();調用string的default ctor

    string tmp=string(0);

_name.string::operator=(tmp);

tmp.string::~string();

cnt=0;

}

顯然name放到初始化列表會更有效率 ,會變成

name.String::String(0);

而cnt這種內建類型則沒有關系,放不放到初始化列表沒有效率上的差別

初始化列表究竟讓編譯器做了什么????

編譯器會一個個操作list中的式子,以適當次序在ctor內安插初始化操作在任何explicit user code 之前。

注意的地方:

       list中的次序是按照members聲明次序決定而不是list 中的排列順序決定。

例如:class x{int i;int j; X(int val):j(val),i(j)}

錯了 i先聲明則i首先賦予val 然后用未初始化的j賦給i。。。

可以這樣X::X(int val):j(val){i=j;}

由于會安插在explicit code 之前 所以沒問題 會變成 j=val;   i=j;

可否用member functions 初始化成員??

答案是可以的,因為和objects相關的this指針已經構建妥當,只是要注意函數調用的member是否已經構建妥當了即可

------         -  -  - ----------       --       --疲憊的結束線-          - -  -     - --            -           -----

name return value TEST:

~~~~1 cl /od 不開優化

#include <iostream>
using namespace std;
class RVO
{
public:

    RVO(){printf("I am in constructor\n");}
    RVO (const RVO& c_RVO) {printf ("I am in copy constructor\n");}
    ~RVO(){printf ("I am in destructor\n");}
    int mem_var;      
};
RVO MyMethod (int i)
{
    RVO rvo1;
    rvo1.mem_var = i;
    return (rvo1);
}
int main()
{
    RVO rvo;rvo=MyMethod(5);
}

輸出:

I am in constructor         //rvo 創建
I am in constructor         // rvo1創建
I am in copy constructor // rvo1賦值給hiddern
I am in destructor          // rvo1解構
I am in destructor          // hiddern解構
I am in destructor         //  rvo 解構

A MyMethod (A &_hiddenArg, B &var)
{
   A retVal;
   retVal.A::A(); // constructor for retVal
   retVal.member = var.value + bar(var);
   _hiddenArg.A::A(retVal);  // the copy constructor for A
   return;
retVal.A::~A();  // destructor for retVal

}
A MyMethod(A &_hiddenArg, B &var)
{
   _hiddenArg.A::A();
   _hiddenArg.member = var.value + bar(var);
   Return
}
~~~~2 cl /o2 代碼同上
output

I am in constructor  //rvo創建
I am in constructor  //hiddern 創建
I am in destructor   //hiddern 解構
I am in destructor   //rvo解構

我不明白的是hiddern 怎么傳給rvo ,我猜可能是編譯器按照bitwise的復制方式進行的,此時編譯器并沒有直接建構結果于rvo上 ,看看下面的試驗:

注:明白了, 結果直接建構在hiddern,然后通過operator = 傳給rvo 。沒有copy ctor因為拷貝構造函數是負責初始化的,而operator = 才是用來賦值的.

經過代碼證明是對的,如果重載賦值運算符 輸出變成:

I am in constructor  //rvo創建
I am in constructor  //hiddern 創建

I am in operator =   //賦值操作~~
I am in destructor   //hiddern 解構
I am in destructor   //rvo解構

~~~~3 cl /od

#include <iostream>
using namespace std;
class RVO
{
public:

    RVO(){printf("I am in constructor\n");}
    RVO (const RVO& c_RVO) {printf ("I am in copy constructor\n");}
    ~RVO(){printf ("I am in destructor\n");}
    int mem_var;      
};
RVO MyMethod (int i)
{
    RVO rvo1;
    rvo1.mem_var = i;
    return (rvo1);
}
void abc(RVO& i){
}
int main()
{
    RVO rvo=MyMethod(5);  //此時定義和賦值放到了一個表達式子
    return 0;
}

output:

I am in constructor           // rvo1 創建 注意 跟上面的第一種情況下的hiddern一樣 rvo并沒有調用ctor
I am in copy constructor   // rvo1 拷貝構造給rvo 此時沒有hiddern了 直接構建rvo了
I am in destructor            // rvo1 析構
I am in destructor            // rvo1 解構

~~~~3 cl /o2  再來~~~~ NRV出馬

I am in constructor           // rvo構建了 
I am in destructor            // rvo析構了

此時 mymethod中的一切都直接反映在rvo身上

ok~~~~~4個代碼完全一樣構造析構拷貝函數個數由2-6不等~~~over~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Feedback

# re: 深入探索C++對象模型讀書筆記 (二)  回復  更多評論   

2010-03-11 09:13 by zmm
不錯,很基礎的

# re: 深入探索C++對象模型讀書筆記 (二)  回復  更多評論   

2010-03-11 13:56 by zmm
~~~~3 cl /o2 再來~~~~ NRV出馬

I am in constructor // rvo構建了
I am in copy constructor // rvo析構了

這里打錯了吧,是in destructor吧~

# re: 深入探索C++對象模型讀書筆記 (二)  回復  更多評論   

2010-03-11 14:01 by rikisand
恩 ~~ 改過來啦 你看的好仔細啊~~

# re: 深入探索C++對象模型讀書筆記 (二)  回復  更多評論   

2010-03-11 16:32 by zmm
@rikisand
呵呵,因為沒有看到destroy,所以我運行了一下~
青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            久久久久久97三级| 欧美日韩精品中文字幕| 亚洲美女色禁图| 99精品国产99久久久久久福利| 欧美激情bt| 午夜欧美精品| 亚洲精品系列| 免费观看30秒视频久久| 亚洲影院在线观看| 亚洲精品久久嫩草网站秘色| 久久精品日产第一区二区| 亚洲欧美春色| 99视频在线观看一区三区| 一区二区三区无毛| 国产日韩一区二区三区在线| 国产精品成人va在线观看| 亚洲免费高清视频| 亚洲国产一区二区a毛片| 亚洲视频综合| 亚洲视频一区在线观看| 亚洲人成在线免费观看| 亚洲婷婷免费| 亚洲成人在线网| 欧美主播一区二区三区美女 久久精品人 | 亚洲欧洲日本mm| 欧美国产另类| 久久亚洲精品欧美| 久久久欧美精品| 欧美专区在线观看| 久久精品一区中文字幕| 久久国产手机看片| 久久国产精品第一页| 欧美自拍偷拍| 久久久久久9| 美日韩丰满少妇在线观看| 亚洲人成网站777色婷婷| 欧美精品一区三区在线观看| 欧美高清视频www夜色资源网| 男女激情久久| 欧美日韩国产精品| 国产精品欧美一区二区三区奶水| 国产精品免费一区二区三区在线观看| 欧美天天在线| 国产热re99久久6国产精品| 国产一区免费视频| 亚洲成色最大综合在线| 日韩视频不卡中文| 午夜日韩视频| 免费一区二区三区| 亚洲精品日韩综合观看成人91| 99re在线精品| 亚洲大胆人体在线| 亚洲国产精品久久久久秋霞蜜臀| 亚洲人成人99网站| 亚洲欧美国产日韩天堂区| 久久精品盗摄| 欧美日韩国产91| 国产精品欧美精品| 激情久久久久久久| 99精品国产一区二区青青牛奶| 一本一本久久a久久精品牛牛影视| 亚洲在线观看视频网站| 久久琪琪电影院| 亚洲激情专区| 亚洲午夜久久久| 亚洲精品国产拍免费91在线| 亚洲欧美经典视频| 欧美二区在线播放| 国产欧美一区二区视频| 日韩视频不卡| 久久一区中文字幕| 亚洲视频日本| 亚洲国产精品久久久久秋霞不卡| 一区二区三区国产在线观看| 久久国产精品一区二区三区四区 | 欧美一级一区| 久久综合九色欧美综合狠狠| 欧美深夜福利| 亚洲国产日日夜夜| 午夜精品在线观看| 亚洲激情视频在线| 欧美成人国产va精品日本一级| 一区二区三区欧美亚洲| 蜜桃视频一区| 在线观看成人小视频| 午夜精品在线观看| 一区二区三区不卡视频在线观看| 久久色在线播放| 国产精品欧美精品| 亚洲一区二区欧美日韩| 欧美成人tv| 欧美在线看片| 欧美日韩免费观看一区| 亚洲丰满在线| 免费在线看成人av| 久久都是精品| 国产农村妇女精品一区二区| 亚洲深夜福利网站| 日韩一二三区视频| 欧美人交a欧美精品| 亚洲免费观看| 一区二区三区你懂的| 亚洲午夜一区二区三区| 亚洲国产91色在线| 欧美成人情趣视频| 亚洲精品网站在线播放gif| 麻豆精品精品国产自在97香蕉| 欧美一区网站| 国内精品嫩模av私拍在线观看 | 欧美日韩福利| 亚洲男人影院| 亚洲尤物在线| 国产日韩欧美一区二区三区在线观看 | 亚洲第一页在线| 美女任你摸久久| 久久久久综合一区二区三区| 在线色欧美三级视频| 欧美成在线视频| 欧美理论视频| 亚洲欧美韩国| 你懂的国产精品| 最新中文字幕亚洲| 欧美日韩一区二区视频在线观看 | 亚洲精品一区二区三区在线观看| 欧美成人免费全部| 亚洲毛片网站| 亚洲性视频网址| 一区精品久久| 亚洲激情精品| 久久精品欧美日韩精品| 欧美日韩免费在线视频| 亚洲一区二区成人| 欧美成人午夜剧场免费观看| 亚洲第一级黄色片| 欧美在线观看www| 久久九九免费视频| 含羞草久久爱69一区| 欧美在线高清| 蜜桃av一区二区在线观看| 狠狠入ady亚洲精品| 久久国产黑丝| 免费日韩成人| 日韩亚洲一区在线播放| 欧美日韩精品综合| 一区二区三区国产精品| 午夜激情久久久| 国产在线视频欧美一区二区三区| 欧美一级黄色网| 免费在线看成人av| 亚洲精品久久久久久久久久久久久| 蜜乳av另类精品一区二区| 亚洲国内精品在线| 亚洲午夜精品久久| 国产婷婷色一区二区三区| 久久久91精品国产| 亚洲日本欧美日韩高观看| 亚洲婷婷免费| 国产午夜精品久久| 农夫在线精品视频免费观看| 亚洲美女性视频| 久久久精品国产免费观看同学| 影音先锋亚洲电影| 欧美日韩精品在线| 久久成人久久爱| 91久久亚洲| 久久精品72免费观看| 1769国产精品| 国产精品久久久久aaaa樱花| 久久国产综合精品| 亚洲美女视频| 噜噜噜在线观看免费视频日韩| 日韩一级片网址| 国语自产在线不卡| 国产精品分类| 免费观看成人| 欧美一区成人| 一区二区三区久久精品| 美女露胸一区二区三区| 亚洲欧美在线看| 亚洲精品国精品久久99热一| 国产精品视频久久一区| 女生裸体视频一区二区三区| 亚洲一区免费网站| 亚洲欧洲日本国产| 你懂的一区二区| 久久高清免费观看| 亚洲一区国产视频| 亚洲精品影院| 亚洲第一级黄色片| 国产一级一区二区| 国产精品成人aaaaa网站| 久热精品在线视频| 欧美一区二区精美| 亚洲一区二区三| 亚洲欧美影院| av成人老司机| 亚洲黄色尤物视频| 一区二区三区在线观看欧美| 国产精品视频福利| 国产精品美女久久久免费|