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

深入探索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>
            亚洲国产精品日韩| 99精品国产热久久91蜜凸| 亚洲素人在线| 一区二区欧美日韩| 亚洲综合日韩在线| 中日韩男男gay无套| 中文欧美日韩| 亚久久调教视频| 美国成人毛片| 欧美性猛片xxxx免费看久爱| 国产精品每日更新在线播放网址| 国产精品成人一区二区| 国产深夜精品福利| 亚洲激情影视| 午夜日韩电影| 欧美大尺度在线观看| 亚洲美女色禁图| 欧美一区二区黄| 欧美精品一区视频| 国产日韩欧美在线播放| 在线精品视频一区二区| 亚洲另类在线一区| 性欧美超级视频| 亚洲大胆人体视频| 亚洲激情综合| 性欧美精品高清| 欧美日韩中国免费专区在线看| 国产一区二区三区免费在线观看| 亚洲欧洲一二三| 久久精品国产视频| 亚洲第一综合天堂另类专| 亚洲综合99| 欧美日本中文| 亚洲激情社区| 欧美在线免费播放| 国内精品美女在线观看| 亚洲激情在线播放| 欧美一区二区观看视频| 亚洲片在线资源| 快she精品国产999| 国产专区精品视频| 亚洲欧美日韩国产| 亚洲免费观看在线视频| 欧美大胆a视频| 在线观看视频亚洲| 久久久噜噜噜久噜久久 | 欧美本精品男人aⅴ天堂| 亚洲精品黄网在线观看| 久久国产精品亚洲77777| 另类尿喷潮videofree| 国产亚洲欧美一级| 欧美一区1区三区3区公司| 欧美在线不卡| 亚洲一级电影| 国产精品亚洲一区| 亚洲欧美激情四射在线日| 99re热这里只有精品视频| 美女视频黄 久久| 国语自产精品视频在线看8查询8| 欧美一区二区女人| 亚洲自拍啪啪| 国产精品一区一区三区| 欧美一级视频| 欧美一区二区三区精品| 国产伦精品一区二区三区视频孕妇| 亚洲私人影院| 亚洲视频你懂的| 欧美三区美女| 亚洲欧美国产不卡| 亚洲欧美日韩在线高清直播| 国产精品夜夜夜| 久久久99国产精品免费| 欧美在线一区二区三区| 影音先锋在线一区| 欧美插天视频在线播放| 欧美成人有码| 亚洲一区免费网站| 亚洲欧美伊人| 伊人久久男人天堂| 亚洲国产99精品国自产| 欧美日韩在线大尺度| 欧美在线视频免费播放| 久久福利毛片| 日韩亚洲精品电影| 亚洲一区尤物| 亚洲国产欧美久久| 中文精品一区二区三区| 黑丝一区二区| 亚洲国内在线| 国产精品爽爽ⅴa在线观看| 久久久久久久久久久成人| 蜜桃久久av一区| 亚洲一区二区免费看| 亚洲午夜小视频| 麻豆精品网站| 国产夜色精品一区二区av| 亚洲欧美成aⅴ人在线观看| 午夜视频一区| 亚洲精品之草原avav久久| 狂野欧美激情性xxxx欧美| 欧美夫妇交换俱乐部在线观看| 亚洲美女诱惑| 狠狠综合久久av一区二区小说| 久久资源在线| 先锋影院在线亚洲| 亚洲精品影院| 欧美va日韩va| 久久一区二区三区国产精品| 亚洲精品免费电影| 一区二区三区在线看| 国产精品乱人伦一区二区 | 久久综合狠狠| av成人国产| 亚洲国产高清aⅴ视频| 欧美先锋影音| 老鸭窝91久久精品色噜噜导演| 99国产精品国产精品久久| 亚洲精品久久久久久久久| 男人的天堂亚洲在线| 欧美在线综合| 欧美在线观看你懂的| 欧美在线一二三四区| 亚洲综合色噜噜狠狠| 亚洲男女毛片无遮挡| 中文欧美字幕免费| 亚洲欧美日本日韩| 在线视频欧美精品| 99re8这里有精品热视频免费| 日韩一级在线观看| 亚洲国产精品va在线看黑人动漫 | 韩国精品一区二区三区| 亚洲欧美怡红院| 国产综合婷婷| 伊人伊人伊人久久| 亚洲区中文字幕| 欧美影院视频| 欧美大片免费观看| 亚洲第一综合天堂另类专| 欧美顶级大胆免费视频| 亚洲欧洲日本一区二区三区| 99国内精品久久| 久久视频一区| 国产精品美女999| 亚洲国产高清自拍| 欧美一级久久| 日韩午夜在线电影| 亚洲欧美日韩另类| 欧美国产精品劲爆| 国产一区美女| 亚洲一区二区三区久久| 久久久噜噜噜久久狠狠50岁| 亚洲国产日韩美| 久久久久国产精品一区二区| 欧美色图一区二区三区| 日韩天堂av| 久久精品最新地址| 欧美一区二区大片| 国产精品永久免费在线| 性色一区二区| 亚洲欧美在线视频观看| 欧美视频在线一区二区三区| 在线播放豆国产99亚洲| 久久精品视频免费| 亚洲一区二区三区欧美| 欧美日本国产视频| 一本一本久久| 亚洲免费播放| 欧美日韩在线播放| 午夜视频在线观看一区二区三区| 亚洲视频一起| 欧美国产日韩精品| 亚洲一区国产精品| 亚洲字幕在线观看| 国产性猛交xxxx免费看久久| 亚洲女性裸体视频| 亚洲尤物在线| 亚洲第一视频| 夜夜嗨av一区二区三区四季av| 欧美视频在线一区二区三区| 午夜在线播放视频欧美| 久久亚洲电影| 欧美在线一级视频| 免费欧美电影| 老牛国产精品一区的观看方式| 亚洲乱码国产乱码精品精可以看| 欧美理论大片| 宅男精品视频| 午夜国产精品影院在线观看| 国产欧美日韩综合一区在线观看| 久久av资源网| 欧美日韩国产综合网| 老色批av在线精品| 国产精品v亚洲精品v日韩精品| 欧美搞黄网站| 在线观看欧美视频| 欧美在线影院| 久久精品国产99精品国产亚洲性色| 米奇777超碰欧美日韩亚洲| 久久亚洲精品中文字幕冲田杏梨| 国产精品vip|