天天看點

cocos2d-x源碼分析::CCCopying關于淺拷貝和深拷貝

在讨論CCCopying這個類之前我們先來說一說淺拷貝和深拷貝的問題

在我看來,其實C++很少讨論關于淺拷貝和深拷貝的内容,我們可以看一下下面的代碼

int main() {
	int *a = new int(10);
	int *b, *c;
	*b = *a; //深拷貝
	c = a;   //淺拷貝
}
           

*a, *b和*c的值都是10,但是a和c的值與b不同,a和c指向共同的位址,b指向另一個位址,這就是深淺拷貝的差別

C++中大部分的類型,如整型,布爾型,浮點型都沒有深淺拷貝的差別,隻有指針,引用這些位址變量才有差別

對于Java和C#這些封裝了指針操作的語言,用引用進行操作,調用指派号操作符進行拷貝隻能是淺拷貝,是以如果要進行深拷貝,必須根據新建立一個對象,再将新對象進行指派

在Java中通過實作ICloneable可以進行深拷貝,而OC中就是NSCopying,而cocos2d-x是由cocos2d-iphone移植成C++的,是以理所當然就存在了CCCopying(最近新出了cocos2d-x3.0聽說脫離了oc的風格,不過我沒有詳細去了解,這裡大家有興趣的話可以去看看)

一個類通過繼承CCCopying,并覆寫(override)其中的copyWithZone的方法,就可以實作深拷貝。

當然cocos2d-x已經通過CCObject繼承了CCCopying,是以如果大家需要用深拷貝的時候,就隻需要在一個CCObject子類覆寫copyWithZone,然後通過調用方法copy(3.0改成clone)就能夠實作深拷貝

我們現在就可以看一看cocos2d-x實作深拷貝的一些細節

//CCObject.cpp
CCObject* CCObject::copy()
{
    return copyWithZone(0);
}
           

copy函數就是那麼簡單,把職責轉交給了copyWithZone,這裡的傳入參數0,實際上應該是((void*)0),通常用宏NULL來表示

因為CCObject的copyWithZone是未實作的,我們就看一看CCAction的

//CCAction.cpp
CCObject* CCAction::copyWithZone(CCZone *pZone)
{
    CCZone *pNewZone = NULL;
    CCAction *pRet = NULL;
    if (pZone && pZone->m_pCopyObject)
    {
        pRet = (CCAction*)(pZone->m_pCopyObject);
    }
    else
    {
        pRet = new CCAction();
        pNewZone = new CCZone(pRet);
    }
    //copy member data
    pRet->m_nTag = m_nTag;
    CC_SAFE_DELETE(pNewZone);
    return pRet;
}
           

如果傳入參數NULL,很明顯是通過new,建立一個新的記憶體空間,然後再對成員變量進行拷貝,最後傳回,這就是深拷貝的操作過程

其實在cocos2d-x這個引擎的C++架構中,這個CCCopying個人認為作用是不太大的,大家權當了解就好

繼續閱讀