說我們有這個類
struct BigArray{
int operator[](size_t i)const{return m_data[i];}
int& operator[](size_t i){return m_data[i];}
private:
int m_data[10000000];
};
現在說,我們有兩個實例:
BigArray a;
a[0]=1;//initializaation etc
BigArray b=a;
在這一點上,我們希望這個不變
assert(a[0]==b[0]);
默認複印ctor確保這個不變,但是以犧牲深度拷貝e爲代價修復對象。我們可能會嘗試像這樣的加速
struct BigArray{
BigArray():m_data(new int[10000000]){}
int operator[](size_t i)const{return (*m_data)[i];}
int& operator[](size_t i){return (*m_data)[i];}
private:
shared_ptr<int> m_data;
};
這也將滿足不變,沒有深層複製,所以一切都很好。 現在使用這種新的實現我們做
b[0]=2;
現在,我們希望這個工作一樣的深拷貝的情況下 斷言(A [0] = B [0]!); 但它失敗。爲了解決這個問題,我們需要一個細微的變化:
struct BigArray{
BigArray():m_data(new int[10000000]){}
int operator[](size_t i)const{return (*m_data)[i];}
int& operator[](size_t i){
if(!m_data.unique()){//"detach"
shared_ptr<int> _tmp(new int[10000000]);
memcpy(_tmp.get(),m_data.get(),10000000);
m_data=_tmp;
}
return (*m_data)[i];
}
private:
shared_ptr<int> m_data;
};
現在我們有一個類時,只需要常量的訪問,並且需要非const訪問時,深拷貝是淺複製。這是「shared_data」指針概念背後的想法。 const調用不會深度複製(他們稱之爲「分離」),而非const則在深度複製(如果共享)。它也增加了運營商的頂部一些語義==使得它不只是比較指針,但數據一樣,所以這將工作:
BigArray b=a;//shallow copy
assert(a==b);//true
b[0]=a[0]+1;//deep copy
b[0]=a[0];//put it back
assert(a==b);//true
這種技術是調用COW(寫入時複製)和自從C++出現以來一直存在。它也非常脆弱 - 上面的例子似乎起作用,因爲它很小並且用例很少。在實踐中,它很少會遇到麻煩,事實上C++ 0x已經廢棄了COW字符串。所以謹慎使用。
這Qt的東西仍然讓我困惑:) – 2010-04-17 12:34:09