除了定義拷貝控制成員,管理資源的類通常還定義了乙個名為swap的函式。為了交換兩個物件我們需要進行一次拷貝和兩次賦值。
hasptr temp = v1;
//建立v1的值的乙個臨時副本
v1 = v2;
//將v2的值賦予v1()
v2 = temp;
//將儲存的v1的值賦予v2
拷貝乙個類值的hasptr會分配乙個新string並將其拷貝到hasptr指向的位置,而這些拷貝中的記憶體分配都是不必要的。我們更希望swap交換指標,而不是分配string的新副本
string *temp = v1.ps;
//為v1.ps中的指標建立乙個副本
v1.ps = v2.ps;
//將v2.ps中的指標賦予v1.ps
v2.ps = temp;
//將儲存的v1.ps中原來的指標賦予v2.ps
編寫自己的swap函式
class
hasptr
;inline
swap
(hasptr &lhs, hasptr &rhs)
如果乙個類成員有自己的swap函式版本,就不能呼叫標準庫的std::swap(),應該直接呼叫型別特定的swap函式
在賦值運算中使用swap
定義了swap函式的類,通常用swap來定義它們的賦值運算子,這些運算子使用了一種名為拷貝並交換(copy and swap)的技術。這種技術將左側運算物件與右側物件的乙個副本進行交換:
//注意rhs是按值傳遞的,意味著hasptr的拷貝建構函式將右側運算物件中的string拷貝到rhs
hasptr& hasptr::
operator
=(hasptr rhs)
該版本中,並非是引用傳遞,而是值傳遞,rhs是右側運算物件的乙個副本,引數傳遞時拷貝hasptr的操作會分配該物件string的乙個新副本。
在swap呼叫之後,*this中的指標成員指向新分配的string——右側運算物件中string的乙個副本。當賦值運算子結束時,rhs被銷毀,hasptr中的析構函式被執行。此析構函式delete rhs現在指向的記憶體,即,釋放掉左側運算物件中原來的記憶體。
這個技術自動處理了自賦值的情況,它通過在改變左側運算物件之前拷貝右側物件保證了字賦值的正確。
解釋:swap(hasptr&, hasptr&)中對swap的呼叫不會導致遞迴迴圈
解答:在swap函式中又呼叫了swap來交換ps和i,但這兩個型別為指標和整型,屬於內建型別。因此函式呼叫中的swap呼叫被解析為std::swap,而不是hasptr特定版本的swap函式,所以不會導致遞迴呼叫。
為你的類值版本的hasptr類編寫swap函式
inline
void
swap
(hasptr &lhs, hasptr &rhs)
為你的hasptr類定義乙個《運算子,並定義乙個hasptr的vector。為這個vector新增一些元素,並對它執行sort。注意何時會呼叫swap
《運算子直接返回兩個hasptr的ps指向的string的比較結果即可,但需要注意的是,它應該被宣告為const。
#include
#include
#include
#include
using
namespace std;
class
hasptr
//預設建構函式
hasptr
(const hasptr& p):ps
(new
string
(*p.ps)),
i(p.i)
//拷貝建構函式
hasptr&
operator=(
const hasptr&);
//拷貝賦值運算子
hasptr&
operator=(
const string&);
//賦予新string
string&
operator*(
);//解引用
bool
operator
<
(const hasptr&
)const
;//比較運算
~hasptr()
;//析構函式
private
: string* ps;
int i;};
hasptr::
~hasptr()
inline hasptr& hasptr::
operator=(
const hasptr & rhs)
hasptr& hasptr::
operator=(
const string& rhs)
string& hasptr::
operator*(
)inline
void
swap
(hasptr& lhs, hasptr& rhs)
bool hasptr::
operator
<
(const hasptr& rhs)
const
intmain()
cout << endl;
sort
(v.begin()
, v.
end())
;for
(auto p : v)
cout << endl;
return0;
}
類指標的hasptr版本會從swap函式中受益嗎?
預設的swap版本簡單交換兩個物件的非靜態成員,對於hasptr來言,就是交換string指標ps、引用計數指標use和整型值i。因此,預設的swap版本能夠正確處理類指標hasptr的交換,專用swap版本不會有更多受益。
過載 操作符 c primer
istream operator istream in,sales item s double price in s.isbn s.units sold price check that the inputs succeeded if in s.revenue s.units sold price ...
C Primer 過載操作符與轉換
1.不能通過連線其他合法符號來建立任何新的操作符,例如試圖定義乙個operator 操作符以提供求冪操作是非法的 用於內建型別的操作符其含義不能改變,例如 int operator int,int 就是非法的 也不能為任何內建型別定義額外的新的操作符,例如不能定義接受兩個陣列型別運算元的operat...
足跡C primer 26 順序容器操作
forward list 有自己專有版本的insert和emplace forward list 不支援push back和emplace back vector,string 不支援push front和emplace front c.push back t c.emplace back args...