HasPtr类
行为像值的类
class HasPtr
{
public:
HasPtr(const string& s = string()) : ps(new string(s)), i(0) {};
HasPtr(const HasPtr& hp) : ps(new string(*hp.ps)), i(hp.i) {};
//重载赋值运算符
HasPtr& operator=(const HasPtr& hp);
private:
string* ps;
int i;
};
HasPtr& HasPtr::operator=(const HasPtr& hp)
{
string* temp_ps = new string(*hp.ps);
delete ps; //销毁对象原本的ps
ps = temp_ps; //指向hp的新空间
i = hp.i;
return *this;
}
行为像指针的类
class HasPtr
{
public:
HasPtr(const string& s = string()) : ps(new string(s)), i(0), use(new size_t(1)) {};
HasPtr(const HasPtr& hp) : ps(new string(*hp.ps)), i(hp.i), use(hp.use) { ++*use; };
HasPtr& operator=(const HasPtr& hp);
~HasPtr() { delete ps; };
private:
string* ps;
int i;
size_t* use;
};
HasPtr& HasPtr::operator=(const HasPtr& rhs)
{
++*rhs.use;
if (--*use == 0)
{
delete use;
delete ps;
}
ps = rhs.ps;
i = rhs.i;
use = rhs.use;
return *this;
}
TreeNode/BinStrTree类
//定义行为像值的类TreeNode
class TreeNode
{
public:
TreeNode() {};
TreeNode(const TreeNode& rhs) : value(rhs.value), count(rhs.count),
left(new TreeNode(*rhs.left)), right(new TreeNode(*rhs.right)) {};
TreeNode& operator=(const TreeNode&);
~TreeNode() { delete left; delete right; };
private:
string value;
int count;
TreeNode* left;
TreeNode* right;
};
TreeNode& TreeNode::operator=(const TreeNode& rhs)
{
//copy value
value = rhs.value;
count = rhs.count;
//copy pointer
auto temp_left = *rhs.left;
auto temp_right = *rhs.right;
delete left;
delete right;
left = new TreeNode(temp_left);
right = new TreeNode(temp_right);
return *this;
}
//定义行为像指针的类TreeNode
class BinStrTree
{
public:
BinStrTree() : used(new size_t(1)) {};
BinStrTree(const BinStrTree& rhs) : root(rhs.root), used(rhs.used) { ++*rhs.used; };
BinStrTree& operator=(const BinStrTree& rhs);
private:
TreeNode* root;
size_t* used;
};
BinStrTree& BinStrTree::operator=(const BinStrTree& rhs)
{
++*rhs.used;
if (--*used == 0)
{
delete root;
delete used;
}
root = rhs.root;
used = rhs.used;
return *this;
}
Message/Floder类
对应于13.4节的内容及习题
Message.h
#pragma once
#include<set>
#include<string>
using namespace std;
class Floder;
class Message
{
friend class Floder;
friend void swap(Message&, Message&);
public:
// construct func
explicit Message(const string& str = "") : contents(str) {};
// copy control members
Message(const Message&);
Message(Message&& m) : contents(std::move(m.contents)) { move_Floders(&m); };
Message& operator=(const Message&);
Message& operator=(Message&&);
~Message();
// member func
void save(Floder&);
void remove(Floder&);
void addFld(Floder*);
void remFld(Floder*);
private:
string contents;
set<Floder*> floders;
void add_to_floders(const Message&);
void remove_from_floders();
void move_Floders(Message* m);
};
class Floder
{
friend class Message;
public:
Floder() {};
void addMsg(Message *);
void remMsg(Message *);
private:
set<Message*> messages;
};
Message.cpp
#include"Message.h"
// ===== Message =====
void Message::save(Floder& _f)
{
floders.insert(&_f);
_f.addMsg(this);
}
void Message::remove(Floder& _f)
{
floders.erase(&_f);
_f.remMsg(this);
}
void Message::add_to_floders(const Message& _m)
{
//让每个包含m的floder添加this
for (auto f : _m.floders)
f->addMsg(this);
}
Message::Message(const Message& _m) : contents(_m.contents), floders(_m.floders)
{
add_to_floders(_m);
}
void Message::remove_from_floders()
{
for (auto f : floders)
f->remMsg(this);
}
Message::~Message()
{
remove_from_floders();
}
Message& Message::operator=(const Message& rhs)
{
remove_from_floders();
contents = rhs.contents;
floders = rhs.floders;
add_to_floders(rhs);
return *this;
}
Message& Message::operator=(Message&& rhs)
{
if (this != &rhs)
{
remove_from_floders();
contents = std::move(rhs.contents);
move_Floders(&rhs);
}
return *this;
}
void swap(Message& lhs, Message& rhs)
{
using std::swap;
for (auto f : lhs.floders)
f->remMsg(&lhs);
for (auto f : rhs.floders)
f->remMsg(&rhs);
swap(lhs.floders, rhs.floders);
swap(lhs.contents, rhs.contents);
for (auto f : lhs.floders)
f->addMsg(&lhs);
for (auto f : rhs.floders)
f->addMsg(&rhs);
}
void Message::addFld(Floder* _f)
{
floders.insert(_f);
}
void Message::remFld(Floder* _f)
{
floders.erase(_f);
}
void Message::move_Floders(Message* m)
{
floders = std::move(m->floders);
//在floders中删除m,并添加this
for (auto f : floders)
{
f->remMsg(m);
f->addMsg(this);
}
m->floders.clear();
}
// ===== Floder =====
void Floder::addMsg(Message* _m)
{
messages.insert(_m);
}
void Floder::remMsg(Message* _m)
{
messages.erase(_m);
}
StrVec类
StrVec.h
#pragma once
#include<string>
#include<memory>
#include<utility>
using namespace std;
class StrVec
{
public:
// construct func
StrVec() : elements(nullptr), first_free(nullptr), cap(nullptr) {};
StrVec(const initializer_list<string>&);
// copy control member
StrVec(const StrVec&);
StrVec(StrVec&&) noexcept;
StrVec& operator=(const StrVec&);
StrVec& operator=(StrVec&&) noexcept;
~StrVec() {};
// member func
void push_back(const string&);
void push_back(string&&);
size_t size() const { return first_free - elements; }
size_t capacity() const { return cap - elements; }
string* begin() const { return elements; }
string* end() const { return first_free; }
void reserve(const size_t&);
void resize(const size_t&, const string&);
string& getvalue(size_t index) { return *(elements + index); };
private:
allocator<string> alloc; //为string元素分配内存
void chk_n_alloc() { if (size() == capacity()) reallocate(); }; //如果大小等于容量,则重新分配空间
pair<string*, string*> alloc_n_copy(const string*, const string*);
void free(); //销毁元素并释放内存
void reallocate(); //重新分配内存空间
string* elements; // pointer to first element
string* first_free; // pointer to the next pos of last element
string* cap; // pointer to the next pos of alloc
};
StrVec.cpp
#include"StrVec.h"
#include<algorithm>
StrVec::StrVec(const initializer_list<string>& sl)
{
for (auto& s : sl)
push_back(s);
}
void StrVec::push_back(const string& s)
{
chk_n_alloc();
alloc.construct(first_free++, s); //在first_free处添加元素s,并移动指针
}
void StrVec::push_back(string&& s)
{
chk_n_alloc();
alloc.construct(first_free++, std::move(s)); //在first_free处添加元素s的右值,并移动指针
}
pair<string*, string*> StrVec::alloc_n_copy(const string* b, const string* e)
{
//分配新空间
auto data = alloc.allocate(e - b);
//初始化并返回一个pair
return make_pair(data, uninitialized_copy(b, e, data));
}
void StrVec::free()
{
if (elements)
{
for_each(elements, first_free, [this](string& s) {alloc.destroy(&s); });
//销毁所有元素
//for (auto p = first_free; p != elements; )
// alloc.destroy(--p);
//释放内存
alloc.deallocate(elements, cap - elements);
}
}
StrVec::StrVec(const StrVec& s)
{
//调用alloc_n_copy分配空间以容纳与s中一样多的元素
auto newdata = alloc_n_copy(s.begin(), s.end());
elements = newdata.first;
first_free = cap = newdata.second;
}
StrVec::StrVec(StrVec&& s) noexcept
{
auto newdata = alloc_n_copy(s.begin(), s.end());
elements = newdata.first;
first_free = cap = newdata.second;
s.elements = s.first_free = s.cap = nullptr;
}
StrVec& StrVec::operator=(const StrVec& rhs)
{
//调用alloc_n_copy分配空间以容纳与rhs中一样多的元素
auto data = alloc_n_copy(rhs.begin(), rhs.end());
free();
elements = data.first;
first_free = cap = data.second;
return *this;
}
StrVec& StrVec::operator=(StrVec&& rhs) noexcept
{
if (this != &rhs)
{
//调用alloc_n_copy分配空间以容纳与rhs中一样多的元素
auto data = alloc_n_copy(rhs.begin(), rhs.end());
free();
elements = data.first;
first_free = cap = data.second;
rhs.elements = rhs.first_free = rhs.cap = nullptr;
}
return *this;
}
void StrVec::reallocate()
{
// newcapacity表示当前内存空间的两倍大小
auto newcapacity = size() ? 2 * size() : 1;
// 分配新内存
auto newdata = alloc.allocate(newcapacity);
// 将数据从旧内存移动到新内存
auto dest = newdata;
auto elem = elements;
for (size_t i = 0; i != size(); ++i)
alloc.construct(dest++, move(*elem++));
free(); //完成移动后释放旧内存空间
elements = newdata;
first_free = dest;
cap = elements + newcapacity;
}
void StrVec::reserve(const size_t& n)
{
// 分配新内存
auto newdata = alloc.allocate(n);
// 将数据从旧内存移动到新内存
auto dest = newdata;
auto elem = elements;
for (size_t i = 0; i != size(); ++i)
alloc.construct(dest++, move(*elem++));
free(); //完成移动后释放旧内存空间
elements = newdata;
first_free = dest;
cap = elements + n;
}
void StrVec::resize(const size_t& n, const string& s = string())
{
if (n < size())
{
for (auto it = elements + n; it != first_free; it++)
alloc.destroy(it);
alloc.deallocate(elements + n, size()-n);
}
else
{
for(int i = 0; i< n - size(); ++i)
push_back(s);
}
}
Homework
Test 13.5
#include<string>
using std::string;
class HasPtr
{
public:
HasPtr(const string& s = string()) : ps(new string(s)), i(0) {};
HasPtr(const HasPtr& hp) : ps(new string(*hp.ps)), i(hp.i) {};
private:
string* ps;
int i;
};
Test 13.8
class HasPtr
{
public:
HasPtr(const string& s = string()) : ps(new string(s)), i(0) {};
HasPtr(const HasPtr& hp) : ps(new string(*hp.ps)), i(hp.i) {};
//重载赋值运算符
HasPtr& operator=(const HasPtr& hp);
private:
string* ps;
int i;
};
HasPtr& HasPtr::operator=(const HasPtr& hp)
{
string* temp_ps = new string(*hp.ps);
delete ps; //销毁对象原本的ps
ps = temp_ps; //指向hp的新空间
i = hp.i;
return *this;
}
Test 13.13
struct X
{
X() { cout << "X()" << endl; }
X(const X&) { cout << "X(const X&)" << endl; }
X& operator=(const X&) { cout << "X& operator=(const X&)" << endl; };
~X() { cout << "~X()" << endl; };
};
void func(X& x1, X x2)
{
cout << "func end" << endl;
}
int main()
{
X x0;
cout << "==========================" << endl;
func(x0, X());
cout << "==========================" << endl;
auto xp = new X();
cout << "==========================" << endl;
vector<X> xvec{ X() };
return 0;
}
Test 13.14
static int seq = 0;
class numbered
{
public:
numbered() : mysn(seq++){ };
int mysn;
//numbered& operator=(numbered&);
};
void f(numbered s)
{
cout << s.mysn << endl;
}
int main()
{
numbered a, b = a, c = b;
f(a);
f(b);
f(c);
return 0;
}
最后输出的三个结果相同,都是0
Test 13.15
static int seq = 0;
class numbered
{
public:
numbered() : mysn(seq++){ };
numbered(const numbered &) : mysn(seq++) { };
int mysn;
};
void f(numbered s)
{
cout << s.mysn << endl;
}
int main()
{
numbered a, b = a, c = b;
f(a);
f(b);
f(c);
return 0;
}
输出的结果为3 4 5
Test 13.16
static int seq = 0;
class numbered
{
public:
numbered() : mysn(seq++){ };
numbered(const numbered &) : mysn(seq++) { };
int mysn;
};
void f(numbered& s)
{
cout << s.mysn << endl;
}
int main()
{
numbered a, b = a, c = b;
f(a);
f(b);
f(c);
return 0;
}
输出的结果为0 1 2
Test 13.17
见Test 13.13-13.17
Test 13.18
struct Employee
{
public:
Employee() {};
Employee(const string& s) : name(s), id(++seq) {};
string name;
int id;
private:
static int seq;
};
int Employee::seq = 0;
Test 13.19
struct Employee
{
public:
Employee() {};
Employee(const string& s) : name(s), id(++seq) {};
Employee(const Employee& e) : name(e.name), id(++seq) { };
string name;
int id;
Employee& operator=(const Employee& e) { name = e.name; return *this; };
private:
static int seq;
};
int Employee::seq = 0;
int main()
{
Employee e1("hj");
Employee e2 = e1;
cout << e2.id << e1.id;
return 0;
}
Test 13.22
class HasPtr
{
public:
HasPtr(const string& s = string()) : ps(new string(s)), i(0) {};
HasPtr(const HasPtr& hp) : ps(new string(*hp.ps)), i(hp.i) {};
HasPtr& operator=(const HasPtr& hp);
~HasPtr() {};
private:
string* ps;
int i;
};
Test 13.23
Test 13.26
class strblob
{
friend class strblobptr;
friend class conststrblobptr;
public:
typedef vector<string>::size_type size_type;
strblob() : data(make_shared<vector<string>>()) {};
strblob(initializer_list<string> il) : data(make_shared<vector<string>>(il)) {}; //可传入任意大小的string链表
strblob(const strblob& sb) : data(make_shared<vector<string>>(*sb.data)) {};
size_type size() const { return data->size(); } //函数体调用的size()是vector的size()成员函数
bool empty() const { return data->empty(); }
//添加和删除元素
void push_back(const string& t) { data->push_back(t); };
void pop_back();
//元素访问
string& front();
const string& front() const;
string& back();
const string& back() const;
//迭代器操作
strblobptr begin();
strblobptr end();
//拷贝控制
strblob& operator=(const strblob& sb);
private:
//strblob类的底层是一个vector<string>
shared_ptr<vector<string>> data;
//如果data[i]不合法,抛出一个异常
void check(size_type i, const string& msg) const;
};
//拷贝控制
strblob& strblob::operator=(const strblob& rhs)
{
data = make_shared<vector<string>>(*rhs.data);
return *this;
}
Test 13.27
class HasPtr
{
public:
HasPtr(const string& s = string()) : ps(new string(s)), i(0), use(new size_t(1)) {};
HasPtr(const HasPtr& hp) : ps(new string(*hp.ps)), i(hp.i), use(hp.use) { ++*use; };
HasPtr& operator=(const HasPtr& hp);
~HasPtr() { delete ps; };
private:
string* ps;
int i;
size_t* use;
};
HasPtr& HasPtr::operator=(const HasPtr& rhs)
{
++*rhs.use;
if (--*use == 0)
{
delete use;
delete ps;
}
ps = rhs.ps;
i = rhs.i;
use = rhs.use;
return *this;
}
Test 13.28
//定义行为像值的类TreeNode
class TreeNode
{
public:
TreeNode() {};
TreeNode(const TreeNode& rhs) : value(rhs.value), count(rhs.count),
left(new TreeNode(*rhs.left)), right(new TreeNode(*rhs.right)) {};
TreeNode& operator=(const TreeNode&);
~TreeNode() { delete left; delete right; };
private:
string value;
int count;
TreeNode* left;
TreeNode* right;
};
TreeNode& TreeNode::operator=(const TreeNode& rhs)
{
//copy value
value = rhs.value;
count = rhs.count;
//copy pointer
auto temp_left = *rhs.left;
auto temp_right = *rhs.right;
delete left;
delete right;
left = new TreeNode(temp_left);
right = new TreeNode(temp_right);
return *this;
}
//定义行为像指针的类TreeNode
class BinStrTree
{
public:
BinStrTree() : used(new size_t(1)) {};
BinStrTree(const BinStrTree& rhs) : root(rhs.root), used(rhs.used) { ++*rhs.used; };
BinStrTree& operator=(const BinStrTree& rhs);
private:
TreeNode* root;
size_t* used;
};
BinStrTree& BinStrTree::operator=(const BinStrTree& rhs)
{
++*rhs.used;
if (--*used == 0)
{
delete root;
delete used;
}
root = rhs.root;
used = rhs.used;
return *this;
}
Test 13.30 & 13.31
HasPtr.h
class HasPtr
{
friend void swap(HasPtr&, HasPtr&);
public:
HasPtr(const string& s = string()) : ps(new string(s)), i(0) {};
HasPtr(const HasPtr& hp) : ps(new string(*hp.ps)), i(hp.i) {};
HasPtr& operator=(const HasPtr&);
bool operator<(const HasPtr&) const;
string getstr() const;
private:
string* ps;
int i;
};
inline
void swap(HasPtr& lhs, HasPtr& rhs)
{
using std::swap;
std::cout << "do swap" << std::endl;
swap(lhs.ps, rhs.ps);
swap(lhs.i, rhs.i);
}
HasPtr.cpp
HasPtr& HasPtr::operator=(const HasPtr& hp)
{
string* temp_ps = new string(*hp.ps);
delete ps;
ps = temp_ps;
i = hp.i;
return *this;
}
bool HasPtr::operator<(const HasPtr& rhs) const
{
return *ps < *rhs.ps;
}
string HasPtr::getstr() const
{
return *(this->ps);
}
main.cpp
int main()
{
vector<HasPtr> hv{ HasPtr("bbb"), HasPtr("eee"),HasPtr("ccc"), HasPtr("aaa") };
for (auto& h : hv)
cout << h.getstr() << " ";
cout << endl;
sort(hv.begin(), hv.end());
for (auto& h : hv)
cout << h.getstr() << " ";
return 0;
}
Test 13. 42
StrVec.h
#include<string>
#include<memory>
#include<utility>
using namespace std;
class StrVec
{
public:
// construct func
StrVec() : elements(nullptr), first_free(nullptr), cap(nullptr) {};
StrVec(const initializer_list<string>&);
// copy control member
StrVec(const StrVec&);
StrVec& operator=(const StrVec&);
~StrVec() {};
// member func
void push_back(const string&);
size_t size() const { return first_free - elements; }
size_t capacity() const { return cap - elements; }
string* begin() const { return elements; }
string* end() const { return first_free; }
void reserve(const size_t&);
void resize(const size_t&, const string&);
string& getvalue(size_t index) { return *(elements + index); };
private:
allocator<string> alloc; //为string元素分配内存
void chk_n_alloc() { if (size() == capacity()) reallocate(); }; //如果大小等于容量,则重新分配空间
pair<string*, string*> alloc_n_copy(const string*, const string*);
void free(); //销毁元素并释放内存
void reallocate(); //重新分配内存空间
string* elements; // pointer to first element
string* first_free; // pointer to the next pos of last element
string* cap; // pointer to the next pos of alloc
};
StrVec.cpp
#include"StrVec.h"
#include<algorithm>
StrVec::StrVec(const initializer_list<string>& sl)
{
for (auto& s : sl)
push_back(s);
}
void StrVec::push_back(const string& s)
{
chk_n_alloc();
alloc.construct(first_free++, s); //在first_free处添加元素s,并移动指针
}
pair<string*, string*> StrVec::alloc_n_copy(const string* b, const string* e)
{
//分配新空间
auto data = alloc.allocate(e - b);
//初始化并返回一个pair
return make_pair(data, uninitialized_copy(b, e, data));
}
void StrVec::free()
{
if (elements)
{
for_each(elements, first_free, [this](string& s) {alloc.destroy(&s); });
//销毁所有元素
//for (auto p = first_free; p != elements; )
// alloc.destroy(--p);
//释放内存
alloc.deallocate(elements, cap - elements);
}
}
StrVec::StrVec(const StrVec& s)
{
//调用alloc_n_copy分配空间以容纳与s中一样多的元素
auto newdata = alloc_n_copy(s.begin(), s.end());
elements = newdata.first;
first_free = cap = newdata.second;
}
StrVec& StrVec::operator=(const StrVec& rhs)
{
//调用alloc_n_copy分配空间以容纳与rhs中一样多的元素
auto data = alloc_n_copy(rhs.begin(), rhs.end());
free();
elements = data.first;
first_free = cap = data.second;
return *this;
}
void StrVec::reallocate()
{
// newcapacity表示当前内存空间的两倍大小
auto newcapacity = size() ? 2 * size() : 1;
// 分配新内存
auto newdata = alloc.allocate(newcapacity);
// 将数据从旧内存移动到新内存
auto dest = newdata;
auto elem = elements;
for (size_t i = 0; i != size(); ++i)
alloc.construct(dest++, move(*elem++));
free(); //完成移动后释放旧内存空间
elements = newdata;
first_free = dest;
cap = elements + newcapacity;
}
void StrVec::reserve(const size_t& n)
{
// 分配新内存
auto newdata = alloc.allocate(n);
// 将数据从旧内存移动到新内存
auto dest = newdata;
auto elem = elements;
for (size_t i = 0; i != size(); ++i)
alloc.construct(dest++, move(*elem++));
free(); //完成移动后释放旧内存空间
elements = newdata;
first_free = dest;
cap = elements + n;
}
void StrVec::resize(const size_t& n, const string& s = string())
{
if (n < size())
{
for (auto it = elements + n; it != first_free; it++)
alloc.destroy(it);
alloc.deallocate(elements + n, size()-n);
}
else
{
for(int i = 0; i< n - size(); ++i)
push_back(s);
}
}
main.cpp
int main()
{
fstream fin("infile.txt");
TextQuery dict(fin);
dict.QueryWord("you're");
return 0;
}
Test 13.43
void StrVec::free()
{
if (elements)
{
for_each(elements, first_free, [this](string& s) {alloc.destroy(&s); });
//销毁所有元素
//for (auto p = first_free; p != elements; )
// alloc.destroy(--p);
//释放内存
alloc.deallocate(elements, cap - elements);
}
}
Test 13.44
String.h
#pragma once
#include<memory>
#include<utility>
using std::initializer_list;
using std::allocator;
using std::pair;
class String
{
public:
// construct func
String() : elements(nullptr), first_free(nullptr), cap(nullptr) {};
String(const initializer_list<char>&);
String(const char*);
// copy control member
String(const String&);
String& operator=(const String&);
~String() {};
// member func
void push_back(const char&);
size_t size() const { return first_free - elements; }
size_t capacity() const { return cap - elements; }
char* begin() const { return elements; }
char* end() const { return first_free; }
void reserve(const size_t&);
void resize(const size_t&, const char&);
char getvalue(size_t index) { return *(elements + index); };
private:
allocator<char> alloc; //为char元素分配内存
void chk_n_alloc() { if (size() == capacity()) reallocate(); }; //如果大小等于容量,则重新分配空间
pair<char*, char*> alloc_n_copy(const char*, const char*);
void free(); //销毁元素并释放内存
void reallocate(); //重新分配内存空间
char* elements; // pointer to first element
char* first_free; // pointer to the next pos of last element
char* cap; // pointer to the next pos of alloc
};
String.cpp
#include"String.h"
#include<algorithm>
#include<iostream>
#include <typeinfo>
#include <type_traits>
using std::make_pair;
using std::uninitialized_copy;
using std::for_each;
using std::cout;
using std::endl;
String::String(const initializer_list<char>& sl)
{
for (auto& s : sl)
push_back(s);
}
String::String(const char* c)
{
elements = alloc.allocate(strlen(c));
first_free = elements + strlen(c);
cap = first_free + strlen(c);
}
void String::push_back(const char& s)
{
chk_n_alloc();
alloc.construct(first_free++, s); //在first_free处添加元素s,并移动指针
}
pair<char*, char*> String::alloc_n_copy(const char* b, const char* e)
{
//分配新空间
auto data = alloc.allocate(e - b);
//初始化并返回一个pair
return make_pair(data, uninitialized_copy(b, e, data));
}
void String::free()
{
if (elements)
{
for_each(elements, first_free, [this](char& s) {alloc.destroy(&s); });
//销毁所有元素
//for (auto p = first_free; p != elements; )
// alloc.destroy(--p);
//释放内存
alloc.deallocate(elements, cap - elements);
}
}
String::String(const String& s)
{
//调用alloc_n_copy分配空间以容纳与s中一样多的元素
auto newdata = alloc_n_copy(s.begin(), s.end());
elements = newdata.first;
first_free = cap = newdata.second;
cout << "do String(const String& s)" << endl;
}
String& String::operator=(const String& rhs)
{
//调用alloc_n_copy分配空间以容纳与rhs中一样多的元素
auto data = alloc_n_copy(rhs.begin(), rhs.end());
free();
elements = data.first;
first_free = cap = data.second;
cout << "do String& operator=(const String& rhs)" << endl;
return *this;
}
void String::reallocate()
{
// newcapacity表示当前内存空间的两倍大小
auto newcapacity = size() ? 2 * size() : 1;
// 分配新内存
auto newdata = alloc.allocate(newcapacity);
// 将数据从旧内存移动到新内存
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 + newcapacity;
}
void String::reserve(const size_t& n)
{
// 分配新内存
auto newdata = alloc.allocate(n);
// 将数据从旧内存移动到新内存
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 + n;
}
void String::resize(const size_t& n, const char& s = char())
{
if (n < size())
{
for (auto it = elements + n; it != first_free; it++)
alloc.destroy(it);
alloc.deallocate(elements + n, size() - n);
}
else
{
for (int i = 0; i < n - size(); ++i)
push_back(s);
}
}
Test 13.47
String::String(const String& s)
{
//调用alloc_n_copy分配空间以容纳与s中一样多的元素
auto newdata = alloc_n_copy(s.begin(), s.end());
elements = newdata.first;
first_free = cap = newdata.second;
cout << "do String(const String& s)" << endl;
}
String& String::operator=(const String& rhs)
{
//调用alloc_n_copy分配空间以容纳与rhs中一样多的元素
auto data = alloc_n_copy(rhs.begin(), rhs.end());
free();
elements = data.first;
first_free = cap = data.second;
cout << "do String& operator=(const String& rhs)" << endl;
return *this;
}
Test 13.48
int main()
{
vector<String> svec;
char a[] = "aaa";
char b[] = "bbb";
char c[] = "ccc";
String stra(a);
String strb(b);
String strc(c);
svec.push_back(stra);
svec.push_back(strb);
svec.push_back(strc);
return 0;
}
输出结果:
do String(const String& s)
do String(const String& s)
do String(const String& s)
do String(const String& s)
do String(const String& s)
do String(const String& s)
共执行了6次拷贝构造函数
Test 13.49
Message类
class Message
{
friend class Floder;
friend void swap(Message&, Message&);
public:
// construct func
explicit Message(const string& str = "") : contents(str) {};
// copy control members
Message(const Message&);
Message(Message&& m) :contents(std::move(m.contents)) { move_Floders(&m); };
Message& operator=(const Message&);
Message& operator=(Message&&);
~Message();
// member func
void save(Floder&);
void remove(Floder&);
void addFld(Floder*);
void remFld(Floder*);
private:
string contents;
set<Floder*> floders;
void add_to_floders(const Message&);
void remove_from_floders();
void move_Floders(Message* m);
};
Message& Message::operator=(Message&& rhs)
{
if (this != &rhs)
{
remove_from_floders();
contents = std::move(rhs.contents);
move_Floders(&rhs);
}
return *this;
}
StrVec类
class StrVec
{
public:
// construct func
StrVec() : elements(nullptr), first_free(nullptr), cap(nullptr) {};
StrVec(const initializer_list<string>&);
// copy control member
StrVec(const StrVec&);
StrVec(StrVec&&) noexcept;
StrVec& operator=(const StrVec&);
StrVec& operator=(StrVec&&) noexcept;
~StrVec() {};
// member func
void push_back(const string&);
size_t size() const { return first_free - elements; }
size_t capacity() const { return cap - elements; }
string* begin() const { return elements; }
string* end() const { return first_free; }
void reserve(const size_t&);
void resize(const size_t&, const string&);
string& getvalue(size_t index) { return *(elements + index); };
private:
allocator<string> alloc; //为string元素分配内存
void chk_n_alloc() { if (size() == capacity()) reallocate(); }; //如果大小等于容量,则重新分配空间
pair<string*, string*> alloc_n_copy(const string*, const string*);
void free(); //销毁元素并释放内存
void reallocate(); //重新分配内存空间
string* elements; // pointer to first element
string* first_free; // pointer to the next pos of last element
string* cap; // pointer to the next pos of alloc
};
StrVec::StrVec(StrVec&& s) noexcept
{
auto newdata = alloc_n_copy(s.begin(), s.end());
elements = newdata.first;
first_free = cap = newdata.second;
s.elements = s.first_free = s.cap = nullptr;
}
StrVec& StrVec::operator=(StrVec&& rhs) noexcept
{
if (this != &rhs)
{
//调用alloc_n_copy分配空间以容纳与rhs中一样多的元素
auto data = alloc_n_copy(rhs.begin(), rhs.end());
free();
elements = data.first;
first_free = cap = data.second;
rhs.elements = rhs.first_free = rhs.cap = nullptr;
}
return *this;
}
String类
class String
{
public:
// construct func
String() : elements(nullptr), first_free(nullptr), cap(nullptr) {};
String(const initializer_list<char>&);
String(const char*);
// copy control member
String(const String&);
String(String&&) noexcept;
String& operator=(const String&);
String& operator=(String&&) noexcept;
~String() {};
// member func
void push_back(const char&);
size_t size() const { return first_free - elements; }
size_t capacity() const { return cap - elements; }
char* begin() const { return elements; }
char* end() const { return first_free; }
void reserve(const size_t&);
void resize(const size_t&, const char&);
char getvalue(size_t index) { return *(elements + index); };
private:
allocator<char> alloc; //为char元素分配内存
void chk_n_alloc() { if (size() == capacity()) reallocate(); }; //如果大小等于容量,则重新分配空间
pair<char*, char*> alloc_n_copy(const char*, const char*);
void free(); //销毁元素并释放内存
void reallocate(); //重新分配内存空间
char* elements; // pointer to first element
char* first_free; // pointer to the next pos of last element
char* cap; // pointer to the next pos of alloc
};
String::String(String&& s) noexcept
{
//调用alloc_n_copy分配空间以容纳与s中一样多的元素
auto newdata = alloc_n_copy(s.begin(), s.end());
elements = newdata.first;
first_free = cap = newdata.second;
s.elements = s.cap = s.first_free = nullptr;
cout << "do String(String&& s)" << endl;
}
String& String::operator=(String&& rhs) noexcept
{
if (this != &rhs)
{
//调用alloc_n_copy分配空间以容纳与rhs中一样多的元素
auto data = alloc_n_copy(rhs.begin(), rhs.end());
free();
elements = data.first;
first_free = cap = data.second;
rhs.elements = rhs.first_free = rhs.cap = nullptr;
}
cout << "do String& operator=(String&& rhs)" << endl;
return *this;
}
Test 13.50
int main()
{
vector<String> svec;
char c1[] = "aaa";
char c2[] = "bbb";
String s1("ccc");
String s3(s1);
svec.push_back(s1);
svec.push_back(std::move(s3));
return 0;
}
输出结果:
do String(const String& s)
do String(const String& s)
do String(String&& s) noexcept
do String(String&& s) noexcept
Test 13.53
class HasPtr
{
friend void swap(HasPtr&, HasPtr&);
public:
HasPtr(const string& s = string()) : ps(new string(s)), i(0) {};
HasPtr(const HasPtr& hp) : ps(new string(*hp.ps)), i(hp.i) {};
HasPtr(HasPtr&& hp) noexcept : ps(hp.ps), i(hp.i) { hp.ps = 0; };
HasPtr& operator=(const HasPtr&);
HasPtr& operator=(HasPtr&&) noexcept;
bool operator<(const HasPtr&) const;
string getstr() const;
private:
string* ps;
int i;
};
HasPtr& HasPtr::operator=(HasPtr&& rhs) noexcept
{
if (this != &rhs)
{
delete ps;
ps = rhs.ps;
rhs.ps = 0;
rhs.i = 0;
}
return *this;
}
Test 13.54
因为对于 hp2 = std::move(hp1);
这样的赋值语句来说,两个运算符匹配的一样好,从而产生了二义性。
HasPtr hp1;
HasPtr hp2;
hp2 = std::move(hp1);
Test 13.55
class StrVec
{
public:
//.....
void push_back(const string&);
void push_back(string&&);
//......
};
void StrVec::push_back(const string& s)
{
chk_n_alloc();
alloc.construct(first_free++, s); //在first_free处添加元素s,并移动指针
}
void StrVec::push_back(string&& s)
{
chk_n_alloc();
alloc.construct(first_free++, std::move(s)); //在first_free处添加元素s的右值,并移动指针
}
Test 13.58
Foo.h
#include<vector>
using namespace std;
class Foo
{
public:
Foo sort() &&;
Foo sort() const&;
private:
vector<int> data;
};
Foo.cpp
#include<algorithm>
#include"Foo.h"
Foo Foo::sort() &&
{
std::sort(data.begin(), data.end());
return *this;
}
Foo Foo::sort() const &
{
Foo ret(*this);
std::sort(ret.data.begin(), ret.data.end());
return ret;
}