讀書筆記: Inside the C++ Object Model (2)

March 2nd, 2011

底下是證明 default constructor 不一定會被製造的實驗

exp_def_ctor.h
class CFoo
{
public:
    CFoo();
    
    int get();
    void set(int);
    
private:
    int m_x;
};

class CFoo2
{
public:
    int get();
    void set(int);
    
private:
    int m_x;
};

class CBar
{
public:
    void set(int);
    int get();
    
private:
    CFoo m_foo;
    char* m_szName;    
};

class CBar2
{
public:
    void set(int);
    int get();
    
private:
    CFoo2 m_foo;
    char* m_szName;
};
exp_def_ctor.cpp
#include "exp_def_ctor.h"
#include 
using namespace std;

CFoo::CFoo() {}
int CFoo::get() { return m_x; }
void CFoo::set(int x) { m_x = x; }

int CFoo2::get() { return m_x; }
void CFoo2::set(int x) { m_x = x; }

int CBar::get() { return m_foo.get(); }
void CBar::set(int x) { m_foo.set(x); }

int CBar2::get() { return m_foo.get(); }
void CBar2::set(int x) { m_foo.set(x); }

void main()
{
    CBar bar;
    CBar2 bar2;
    bar.set(3);
    bar2.set(4);
    cout << bar.get() << endl;
    cout << bar2.get() << endl;
}
cppom.mak
CC      = cl
CFLAGS	= /EHsc /Zi /Fd /c
LD      = link
LDARGS  = /INCREMENTAL:NO /DEBUG
RM	    = del /q

.cpp.obj::
    $(CC) $(CFLAGS) $<

test1.exe: exp_def_ctor.obj
	$(LD) exp_def_ctor.obj $(LDARGS) /OUT:test1.exe /PDB:test1.pdb

clean:
	$(RM) *.exe *.obj *.pdb *.idb *.ilk *.bak

all: test1.exe

CFoo2 沒有 constructor,所以 CBar2 不應有 constructor。CFoo 有一個沒作用的 constructor,但在實驗中證明 VC++ 依然去呼叫它

0:000> ln test1!main
d:\home\desktop\research\exp_def_ctor.cpp(19)
(00311100)   test1!main   |  (00311170)   test1!std::endl
Exact matches:
    test1!main (void)
0:000> u 00311100 0031116f
test1!main [d:\home\desktop\research\exp_def_ctor.cpp @ 19]:
00311100 55              push    ebp
00311101 8bec            mov     ebp,esp
00311103 83ec10          sub     esp,10h
00311106 8d4df8          lea     ecx,[ebp-8]
00311109 e882000000      call    test1!CBar::CBar (00311190)
0031110e 6a03            push    3
00311110 8d4df8          lea     ecx,[ebp-8]
00311113 e888ffffff      call    test1!CBar::set (003110a0)
00311118 6a04            push    4
0031111a 8d4df0          lea     ecx,[ebp-10h]
0031111d e8beffffff      call    test1!CBar2::set (003110e0)
00311122 6870113100      push    offset test1!std::endl (00311170)
00311127 8d4df8          lea     ecx,[ebp-8]
0031112a e851ffffff      call    test1!CBar::get (00311080)
0031112f 50              push    eax
00311130 b980083400      mov     ecx,offset test1!std::cout (00340880)
00311135 e896000000      call    test1!std::basic_ostream >::operator<< (003111d0)
0031113a 8bc8            mov     ecx,eax
0031113c e86f000000      call    test1!std::basic_ostream >::operator<< (003111b0)
00311141 6870113100      push    offset test1!std::endl (00311170)
00311146 8d4df0          lea     ecx,[ebp-10h]
00311149 e872ffffff      call    test1!CBar2::get (003110c0)
0031114e 50              push    eax
0031114f b980083400      mov     ecx,offset test1!std::cout (00340880)
00311154 e877000000      call    test1!std::basic_ostream >::operator<< (003111d0)
00311159 8bc8            mov     ecx,eax
0031115b e850000000      call    test1!std::basic_ostream >::operator<< (003111b0)
00311160 33c0            xor     eax,eax
00311162 8be5            mov     esp,ebp
00311164 5d              pop     ebp
00311165 c3              ret

好像很笨,如果把最佳化開下去會怎樣呢?我加了 /O2 之後得到一個異常聰明的結果

0:000> ln test1!main
d:\home\desktop\research\exp_def_ctor.cpp(19)
(00ba4160)   test1!main   |  (00ba4190)   test1!std::basic_string,std::allocator >::assign
Exact matches:
    test1!main (void)
0:000> u 00ba4160 00ba418f
test1!main [d:\home\desktop\research\exp_def_ctor.cpp @ 19]:
00ba4160 6a03            push    3
00ba4162 b910f9bc00      mov     ecx,offset test1!std::cout (00bcf910)
00ba4167 e8b4f1ffff      call    test1!std::basic_ostream >::operator<< (00ba3320)
00ba416c 50              push    eax
00ba416d e88effffff      call    test1!std::endl (00ba4100)
00ba4172 83c404          add     esp,4
00ba4175 6a04            push    4
00ba4177 b910f9bc00      mov     ecx,offset test1!std::cout (00bcf910)
00ba417c e89ff1ffff      call    test1!std::basic_ostream >::operator<< (00ba3320)
00ba4181 50              push    eax
00ba4182 e879ffffff      call    test1!std::endl (00ba4100)
00ba4187 83c404          add     esp,4
00ba418a 33c0            xor     eax,eax
00ba418c c3              ret

完全用數值代入了,不過呢,CBar 和 CFoo 依然有 constructor,CBar2 則沒有

0:000> ln test1!CBar::CBar
(00ba13f0)   test1!CBar::CBar   |  (00ba1400)   test1!std::_Yarn::_Yarn
Exact matches:
    test1!CBar::CBar (void)
0:000> u 00ba13f0 00ba13ff
test1!CBar::CBar:
00ba13f0 8bc1            mov     eax,ecx
00ba13f2 c3              ret
...
0:000> ln test1!CBar2::CBar2
Couldn't resolve error at 'test1!CBar2::CBar2'

C++/C#, 技術文章 | Comments Jump to the top of this page

Comments are closed.

隨便寫寫大家隨便看看的不出名小格子

舊文索引

站內管理