欧美一区二区三区老妇人-欧美做爰猛烈大尺度电-99久久夜色精品国产亚洲a-亚洲福利视频一区二区

c++對(duì)象模型 執(zhí)行期語(yǔ)義

obejct construction and destruction

? 一般而言,constructor和destructor的安插都如預(yù)期那樣:

成都創(chuàng)新互聯(lián)是一家專(zhuān)注于網(wǎng)站制作、成都網(wǎng)站制作與策劃設(shè)計(jì),金口河網(wǎng)站建設(shè)哪家好?成都創(chuàng)新互聯(lián)做網(wǎng)站,專(zhuān)注于網(wǎng)站建設(shè)10年,網(wǎng)設(shè)計(jì)領(lǐng)域的專(zhuān)業(yè)建站公司;建站業(yè)務(wù)涵蓋:金口河等地區(qū)。金口河做網(wǎng)站價(jià)格咨詢(xún):13518219792

{
    Point point;
    //point.Point::Point() 安插于此
    ...
    //point.Point::~Point() 安插于此
}

? 但有些情況desctructor需要放在每一個(gè)離開(kāi)點(diǎn)(此時(shí)object還存活)前,例如swith,goto:

{
    Point point;
    //point.Point::Point() 安插于此
    
    swith ( int(point.x() ) )
    {
        case -1 : 
        ...
        //point.Point::~Point() 安插于此
        return;
        
        case 0 : 
        ...
        //point.Point::~Point() 安插于此
        return;
        
        case 1 : 
        ...
        //point.Point::~Point() 安插于此
        return;
        
        default : 
        ...
        //point.Point::~Point() 安插于此
        return;
        
    }
    
    //point.Point::~Point() 安插于此
}
  • 一般而言,我們會(huì)盡可能將object放于使用它的那個(gè)程序片段附近,如此即可節(jié)省非必要的對(duì)象產(chǎn)生和銷(xiāo)毀

全局對(duì)象

  • c++保證,一定會(huì)在main()中第一次用到global object前,將global object構(gòu)造出來(lái),而在main()結(jié)束前把global object摧毀掉
  • c++中,global objects都被放置于data segment,若顯示為他指定一個(gè)值,此object將以此為初值,否則賦值為0(nonclass亦支持)。但c與此不同,c并不自動(dòng)設(shè)定初值,而是global object只能被一個(gè)常量表達(dá)式設(shè)定初值

? 解決c++ global object constructor和destructor的方法步驟:

  1. 為每一個(gè)需要初始化的文件產(chǎn)生__sti(),內(nèi)含必要的constructor或inline expansions

  2. 在每個(gè)需要內(nèi)存釋放的文件中產(chǎn)生__std(),內(nèi)含必要的destructor或inline expansions

  3. 提供一組rumtime library munch函數(shù):一個(gè)_main()用以調(diào)用可執(zhí)行文件中的所有__sti(),和一個(gè)exit()用以調(diào)用可執(zhí)行文件中的所有__std()

    //matrix_c也就是matrix.c文件名,identity為static object
    __sti__matrix_c__identity()
    {
        identity.Matrix::Matrix();
    }
    
    int main()
    {
        _main();
        ...
        _exit();
    }
    
  • 支持non class objects的靜態(tài)初始化,也意味著支持virtual base classes。因?yàn)閐erived class的pointer或reference存取virtual base class subobject是一種非常量表達(dá)式

局部靜態(tài)對(duì)象

? local static class object保證:

  1. 對(duì)象的constructor只被調(diào)用一次,即使在函數(shù)中可能會(huì)被多次調(diào)用
  2. 對(duì)象的destructor只被調(diào)用一次,即使在函數(shù)中可能會(huì)被多次調(diào)用

? 要支持以上行為,需要導(dǎo)入臨時(shí)性對(duì)象以保護(hù)local static class object,第一次處理此object時(shí),臨時(shí)對(duì)象被賦值為false,此時(shí)constructor被調(diào)用,臨時(shí)對(duì)象被改為true。取地址保證單一的構(gòu)造和析構(gòu)

//如下程序片段
const Matrix& identity()
{
    static Matrix mat_identity;
    //...
    return mat_identity;
}

//編譯器策略之一
static struct Matrix* __0__F3 = 0;

struct Matrix* identity__Fv()
{
    static struct Matrix__lmat__identity;
    //若臨時(shí)性對(duì)象已被建立,什么也別做
    //否則:調(diào)用constructor:__ct__6MatrixFv
    //設(shè)定保護(hù)對(duì)象,使它指向目標(biāo)對(duì)象
    __0__F3 ? 0 : (__ct__6MatrixFv( &__1mat_identity), (__0__F3 = ( &1mat_identity) ) );
    
    //...
}

//destructor在與文件有關(guān)聯(lián)的靜態(tài)內(nèi)存釋放函數(shù)中有條件地被調(diào)用
char __std__stat_0_c_j()
{
    __0__F3 ? __dt__6MatrixFv( __0__F3, 2 ) : 0;
    //...
}

對(duì)象數(shù)組

? 現(xiàn)有如下片段:

Point knots[10];

? 對(duì)于以上數(shù)組,若Point并沒(méi)有定義constructor和destructor,只需配置內(nèi)存存儲(chǔ)元素即可。但若定義了,一般來(lái)說(shuō)會(huì)經(jīng)由一個(gè)或多個(gè)runtime library函數(shù)完成:

void* vec_new(
	void* array,	//數(shù)組起始地址.若不是具名數(shù)組則為0
    size_t elem_size,	//每個(gè)class object的大小
    int elem_count,		//數(shù)組中元素個(gè)數(shù)
    void(*constructor)( void* ),	//class的default constructor的函數(shù)指針
    void ( *destructor )( void*, char )		//class的default destructor的函數(shù)指針
);
    
void* vec_delete
{
    void* array,	//數(shù)組起始地址
    size_t elem_size,	//每個(gè)class object的大小
    int elem_count,		//數(shù)組中元素個(gè)數(shù)
    void ( *destructor )( void*, char )
}

//函數(shù)調(diào)用如下:
vec_new( &knots, sizeof(Point), 10, &Point::Point, 0 );
  • 我們不可以取constructor的地址,只有編譯器可以

  • vec_new的主要功能是將default constructor施行于class object組成的數(shù)組的每個(gè)元素

? 若提供一個(gè)或多個(gè)明顯初值給class object組成的數(shù)組,編譯器會(huì)顯示地初始化前面提供了顯式初值的元素,再用vec_new初始化后面未提供的

new和delete

? new運(yùn)算符看起來(lái)是單一運(yùn)算,但其實(shí)由兩個(gè)步驟完成:

int* pi = new int(5);

//new
int* pi;
if( pi = __new( sizeof( int ) ) ) *pi = 5;		//內(nèi)存分配成功才初始化

//delete與new相似
if( pi != 0 ) __delete( pi );	//pi并不會(huì)清除為0

? 若用constructor配置class object:

//new
Point3d* origin = new Point3d;

Point3d* origin;
if( origin = __new( sizeof(Point3d) ) ) origin = Point3d::Point3d(origin);

//若是exception handling
if( origin = __new( sizeof(Point3d)))
{
    try
    {
        origin = Point3d::Point3d(origin);
    }
    catch(...)
    {
        __delete(origin);
        throw;
    }
}

//delete
delete origin;

if( origin != 0 )
{
    Point3d::~Point3d(origin);
    __delete(origin);
}
  • vec_new有責(zé)任在excption發(fā)生的時(shí)候把內(nèi)存釋放掉

? library對(duì)new運(yùn)算符的實(shí)現(xiàn)。要求每次new傳回獨(dú)一無(wú)二的指針:

extern void* operator new(size_t size)
{
    if( size == 0 ) size == 1;
    
    void* last_alloc;
    while( !(last_alloc == malloc(size)))
    {
        //使用者自己的函數(shù)
        if( _new_handler ) ( *_new_handler )();
        else return 0;
    }
    
    return last_alloc;
}

針對(duì)數(shù)組

? 現(xiàn)有如下片段:

int * p_array = new int[5];

int* p_array = (int*)__new( 5 * sizeof(int));

struct A{ float f1; };
A* p_a = new A[5];

? 以上兩種方式都不會(huì)調(diào)用vec_new,因?yàn)関ec_new的主要功能是將default constructor施行于class object組成的數(shù)組的每個(gè)元素,第二個(gè)例子沒(méi)有定義constructor或destructor。但第一個(gè)實(shí)例會(huì)調(diào)用new operator

? 以下片段會(huì)調(diào)用vec_new:

Point3d* p_array = new Point3d[10];

//轉(zhuǎn)化
Point3d* p_array;
p_array = vec_new( 0, sizeof(Point3d), 10, &Point3d::Point3d, &Point3d::~Point3d );

? 以下兩種delete如今都支持:

int array_size = 10;
Point3d* p_array = new Point3d[array_size];

delete [array_size]p_array;
delete []p_array;
  • delete數(shù)組的元素如何記錄呢?方法是為vec_new()所傳會(huì)的每個(gè)內(nèi)存區(qū)塊配置一個(gè)額外的word,將元素個(gè)數(shù)藏在word中,這種被藏的數(shù)值被稱(chēng)為cookie

? 現(xiàn)有如下片段:

class Point
{
public:
    Point();
    virtual ~Point();
    //...
};

class Point3d: public Point
{
public:
    Point3d();
    virtual ~Point3d();
    //...
};

? 此時(shí),配置內(nèi)含10個(gè)Point3d objects的數(shù)組,Point和Point3d的constructor各被調(diào)用10次。但調(diào)用delete,大有不同:

Point* ptr = new Point3d[10];

//只有~Point()調(diào)用,且只傳遞了Point class object的大小
delete [] ptr;

  • 對(duì)于以上行為,最好的方法是避免一個(gè)base class指針指向一個(gè)derived class objects組成的數(shù)組。但若有這方面需求,以下方法可行:
    for( int ix = 0; ix < elem_count; ++ix )
    {
        Point3d* p = &( (Point3d*) ptr )[ix];
        delete p;
    }
    

placement operator new

? 調(diào)用方式:

Point2w* ptw = new ( arena ) Point2w;	//arena指向內(nèi)存的一個(gè)區(qū)塊,放置新產(chǎn)生的Point2w object

void* operator new( size_t, void* p )
{
    return p;
}

? 但是以上只是placement operator new操作的一半,擴(kuò)充的另一半將class object constuctor自動(dòng)實(shí)施于arena所指地址:

Point2w* ptw = ( Point2w* ) arena;
if( ptw != 0 ) ptw->Point2w::Point2w();
  • placement operator delete會(huì)對(duì)object實(shí)施destructor,但不釋放內(nèi)存

? 對(duì)于"Point2w* ptw = new ( arena ) Point2w;",我們無(wú)法知道arena所指的這塊區(qū)域是否需要先析構(gòu)

  • placement operator new并不支持多態(tài)。因此,arena所表現(xiàn)的真正指針類(lèi)型,要么指向相同類(lèi)型的class,要么是一塊新的內(nèi)存,足夠容納該類(lèi)型的object
    //錯(cuò)的
    Point2w* p2w = new (arena) Point3w;
    

臨時(shí)對(duì)象

  • 凡持有表達(dá)式結(jié)果的臨時(shí)對(duì)象,應(yīng)保留到class object的初始化操作完成
  • 若臨時(shí)對(duì)象被綁定在一個(gè)reference,對(duì)象將殘留直至被初始化的reference聲明結(jié)束,或是scope結(jié)束

當(dāng)前題目:c++對(duì)象模型 執(zhí)行期語(yǔ)義
轉(zhuǎn)載注明:http://chinadenli.net/article14/dsoiege.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供搜索引擎優(yōu)化、品牌網(wǎng)站制作、云服務(wù)器、做網(wǎng)站網(wǎng)站制作

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶(hù)投稿、用戶(hù)轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話(huà):028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)

成都定制網(wǎng)站建設(shè)