C++Primer第五版 第十三章習題答案(31~40)
阿新 • • 發佈:2019-02-01
31:這幾題都是舉例使用動態記憶體管理類,多是程式碼,多寫寫
#include<iostream> #include<string> #include<vector> #include<algorithm> using namespace std; class Hasptr1 { friend void swap(Hasptr1&,Hasptr1&); friend bool operator<(const Hasptr1& s1,const Hasptr1& s2); friend void show(vector<Hasptr1>& vec); public: //建構函式,初始化相關成員 Hasptr1(const string& s = string()):ps(new string(s)),i(0),use(new size_t(1)){} //拷貝建構函式,將引用計數也拷貝過來,並且遞增引用計數 Hasptr1(const Hasptr1& p):ps(p.ps),i(p.i),use(p.use){++*use;} //拷貝賦值運算子 Hasptr1& operator= (const Hasptr1& p1) { ++*p1.use;//首先遞增右側運算子物件的引用計數 if (--*use == 0)//遞減本物件的引用計數,若沒有其他使用者,則釋放本物件的成員 { delete ps; delete use; } ps = p1.ps;//進行拷貝 use = p1.use; i = p1.i; return *this; } //解構函式 ~Hasptr1() { if (*use == 0)//引用計數變為0,說明已經沒有物件再需要這塊記憶體,進行釋放記憶體操作 { delete ps; delete use; } } private: //定義為指標,是我們想將該string物件儲存在動態記憶體中 string *ps; size_t *use;//將計數器的引用儲存 int i; }; inline void swap(Hasptr1& a,Hasptr1& b) { using std::swap; swap(a.ps,b.ps); std::swap(a.i,b.i); cout<<"123"; } bool operator< (const Hasptr1& s1,const Hasptr1& s2) { cout<<"定義的 Operator< 被呼叫"<<endl; return *s1.ps < *s2.ps; } void show(vector<Hasptr1>& vec) { vector<Hasptr1>::iterator it1 = vec.begin(); for (it1; it1 != vec.end(); ++it1) { cout<<*(it1->ps)<<endl; } } int main(int argc, char**argv) { vector<Hasptr1> vec1; Hasptr1 a("l"); Hasptr1 b("llll"); Hasptr1 c("lll"); vec1.push_back(a); vec1.push_back(b); vec1.push_back(c); vector<Hasptr1>::iterator it1 = vec1.begin(); sort(vec1.begin(),vec1.end()); show(vec1); return 0; }
32:類指標的類版本,使用編譯器自帶的swap()函式即可完成目標操作,並不需要自定義一個swap以交換指標所指向的值,所以並不會提升效果
33:我們的目的是對傳入的folder進行修改,傳值的方式會使得我們修改的是其副本,const修飾符使得我們不能對其進行修改。所以都不行
34:
#ifndef MESSAGE_H//防止標頭檔案重複包含 #define MESSAGE_H #include <string> #include <set> using namespace std; class Message { friend class Folder; public: Message(const Message& m):contents(m.contents),folders(m.folders)//拷貝建構函式 { add_to_Folders(m);//拷貝時,將新建立的message的指標新增到每個包含的folder中 } Message& operator=(const Message& mm)//拷貝賦值運算子 { remove_from_Folders();//刪除自身 contents = mm.contents; folders = mm.folders; add_to_Folders(mm);//將本message傳入folder中 return *this } Message(const string &str = ""):contents(str){}//建構函式 void swap(Message& m1,Message& m2) { using std::swap; //先將每個message從其folders中刪除 for(auto f : m1.folders) { f->remMsg(this);//所有包含此message的folder進行刪除操作 } for(auto f : m2.folders) { f->remMsg(this);//所有包含此message的folder進行刪除操作 } swap(m1.folders,m2.folders); swap(m1.contents,m2.contents); for (auto f : m1.folders) { f->addMsg(this);//再進行新增操作 } for (auto f : m2.folders) { f->addMsg(this); } } ~Message()//解構函式 { remove_from_Folders(); } void save(Folder&); void remove(Folder&);//對Folder類的操作函式 private: string contents;//資訊內容 set<Folder*> folders;//包含本message的folder序列 void add_to_Folders(const Message&); void remove_from_Folders();//從folders中刪除本message }; void Message::save(Folder& f) { folders.insert(&f);//將給定folder加入到我們的folders中 f.addMsg(this);//將本message新增到給定folder中 } void Message::remove(Folder& f) { folders.erase(&f);//將給定folder在我們的folders中刪除 f.remMsg(this);//將本message在給定folder中刪除 } void Message::add_to_Folders(const Message& m) { for (auto f : m.folders) { f->addMsg(this); } } void Message::remove_from_Folders() { for (auto f : folders) { f->remMsg(this);//所有包含此message的folder進行刪除操作 } } #endif MESSAGE_H
35:若使用合成的拷貝控制成員,則folders不會更新,所包含資訊錯亂
36:
class Folder { public: Folder(); ~Folder(); Folder& operator=(const Folder&); Folder(const Folder&); void addMsg(Message *m3)//上面需要使用this作為引數,所以這裡需要用指標 { messages.insert(m3); } void remMsg(Message *m4) { messages.erase(m4); } private: set<Message*> messages;//儲存Message的指標 };
37:見34題程式碼
38:當涉及到動態分配記憶體時,拷貝並交換是一個完成該功能的精簡的方式. ,但是在Message類中,並未涉及到動態分配記憶體,這種方法並不會產生任何益處,同時還會因為很多指標操作讓程式變得更復雜難難以實現
39:
void StrVec::alloc_n_move(size_t new_cap)
{
auto newdata = alloc.allocate(new_cap);
auto dest = newdata;
auto elem = elements;
for (size_t i = 0; i != size(); ++i)
alloc.construct(dest++, std::move(*elem++));
free();
elements = newdata;
first_free = dest;
cap = elements + new_cap;
}
void StrVec::reallocate()
{
auto newcapacity = size() ? 2 * size() : 1;
alloc_n_move(newcapacity);
}
void StrVec::reserve(size_t new_cap)
{
if (new_cap <= capacity()) return;
alloc_n_move(new_cap);
}
void StrVec::resize(size_t count)
{
resize(count, std::string());
}
void StrVec::resize(size_t count, const std::string& s)
{
if (count > size()) {
if (count > capacity()) reserve(count * 2);
for (size_t i = size(); i != count; ++i)
alloc.construct(first_free++, s);
}
else if (count < size()) {
while (first_free != elements + count) alloc.destroy(--first_free);
}
}
40:主要為三個指標進行初始化,並將成員進行賦值
StrVec(initializer_list<string>lst){
auto newdata=alloc_n_copy(lst.begin(),lst.end());
elements=newdata.first;
first_free=cap=newdata.second;
}