拷貝控制操作包括:拷貝建構函式、拷貝賦值運算子、移動建構函式、移動賦值運算子和析構函式。
class foo;
這裡有個簡單的規則:如果你需要定義乙個非空的析構函式,那麼,通常情況下你也需要定義乙個拷貝建構函式。
拷貝初始化發生在以下情況:
(1)用「=」定義變數
(2)將乙個物件作為實參傳遞給乙個非引用型別的形參。
(3)從乙個返回型別為非引用型別的函式返回乙個物件。
(4)用{}列表初始化乙個陣列中的元素或乙個聚合類中的成員。
補充:編譯系統在我們沒有自己定義拷貝建構函式時,會在拷貝物件時呼叫預設拷貝建構函式,進行的是淺拷貝。
#include
using
namespace
std;
class student
;student::student()
student::~student()
int main()
上述程式中,由於系統呼叫的是預設拷貝建構函式,沒有重新分配記憶體,兩個指標指向同一塊記憶體,而析構函式呼叫了兩次,引起記憶體洩露。
所以在對含有指標成員的物件進行拷貝時,必須要自己定義拷貝建構函式,使拷貝後的物件指標成員有自己的記憶體空間,即進行深拷貝,這樣就避免了記憶體洩漏發生。
#include
using
namespace
std;
class student
;student::student()
student::student(const student &s)
student::~student()
int main()
class foo;
合成拷貝賦值運算子:
sales_data& sales_data::operator=(const sales_data &rhs)
不能被過載。成員按初始化順序的逆序銷毀。
無論何時乙個物件被銷毀,就會自動呼叫其析構函式:
4.三五法則
可以控制類的拷貝操作:拷貝建構函式、拷貝賦值運算子和析構函式。
(如果乙個類需要自定義析構函式,幾乎肯定它也需要自定義拷貝賦值運算子和建構函式。)
(如果乙個類需要自定義拷貝建構函式,幾乎可以肯定它也需要乙個拷貝賦值運算子)
5.使用=default
在類中用=default修飾成員的宣告,合成的函式將隱式地宣告成內聯的,並且只能對合成版本的成員函式使用。
6.阻止拷貝
定義刪除的函式 =delete 雖然進行了宣告,但不能以任何方式使用。=delete必須出現在第一次宣告的時候。注:析構函式不能是刪除的成員
c++11發布前是通過private來阻止拷貝
class privatecopy
管理類外資源的類必須定義拷貝控制成員。
1.行為像指標的類
class hasptr
//對ps指向的string 每個hasptr都有自己的拷貝
hasptr(const hasptr &p):ps(new
string(*p.ps)),i(p.i){}
hasptr& operator=(const hasptr &);
//釋放ps
~hasptr()
private:
string *ps;
int i;
}
hasptr::operatpr = (const hasptr& has)
2.定義行為像指標的類
引用計數的工作方式如下:
class
hasptr
//拷貝建構函式拷貝所有三個成員,並遞增計數器
hasptr(const hasptr& has) : ps(has.ps), i(has.i), use(has.use)
hasptr& operator = (const hasptr& has);
~hasptr();
private:
string* ps;
int i;
size_t* use; // 計數
};
hasptr::hasptr& operator = (const hasptr& has)
ps = has.ps;
i = has.i;
use = has.use;
return *this;
} hasptr::~hasptr()
}
管理類外資源的類通常還定義了名為swap的函式。
class
hasptr
inline void swap(hasptr &lhs ,hasptr &rhs)
在賦值運算子中使用swap,拷貝並交換技術。
//異常安全的,且能正確處理自賦值
hasptr& hasptr::operator=(hasptr rhs)
類似於對應的拷貝操作,但它們從給定物件「竊取」資源而不是拷貝資源
//類似於拷貝建構函式,但注意這裡的引用引數是乙個右值引用
//通常不分配任何資源,因此移動通常不會丟擲異常,所以加上noexcept
strvec::strvec(strvec &&s)noexcept
:elements(s.elements),first_free(s.first_free),cap(s.cap)
不丟擲異常的移動建構函式和移動賦值運算子必須標記為noexcept
strvec::strvec operator=(strvec &&rhs) noexcept
return *this;
}
只有當乙個類沒有定義任何自己版本的拷貝控制成員,且類的每個非static資料成員都可以移動時,編譯器才會為它合成移動建構函式或移動賦值運算子。
struct x;
struct hasx
x x,x2=move(x);//使用合成的移動建構函式
hasx hx,hx2=move(x);//使用合成的移動建構函式
學習記錄 js深拷貝 淺拷貝
js 的資料型別有兩種,一種是基本資料型別 string number boolean null undefined symbol 一種是引用資料型別 object array function 基本資料型別是放在棧記憶體的,而引用資料型別是存放在堆記憶體的,它會在棧記憶體裡面存放乙個指向堆記憶體的...
C primer學習 拷貝控制 1
1 我們使用 定義變數 2 從乙個返回型別為非引用的函式返回物件 3 用花括號列表初始化乙個陣列中的元素或者乙個聚合類的成員.4 某些類型別對它們所分配的物件使用拷貝初始化.point global point foo bar point arg 第1處 第4,5初 return heap 第6處 ...
C primer學習 拷貝控制 3
strblob const strblob rhs 拷貝初始化 strblob operator const strblob rhs 練習 定義乙個使用引用計數的hasptr類class hasptr 在拷貝建構函式中定義三個成員,並且初始化引用計數為1 hasptr const hasptr h ...