//13.8
HasPtr& operator= (const Hasptr& HP)
{
string *p = new string(*HP.ps);//new返回的是指向分配好内存、创建了对象的指针
delete ps;//销毁原string
ps = p; //指向新的string
i = HP.i;
return *this;//返回值
}
//13.13
#include <iostream>
#include <vector>
#include <initializer_list>
using namespace std;
class X {
public:
X() { std::cout << "X()" << std::endl; }
X(const X&) { std::cout << "X(const X&)" << std::endl; }
X& operator=(const X&)
{
std::cout << "X& operator=(const X&)" << std::endl;
return *this;
}
~X() { std::cout << "~X()" << std::endl; }
};
void f(const X& rx, X x)
{
vector<X> vec;
vec.reserve(2);
vec.push_back(rx);
vec.push_back(x);
}
int main()
{
X* px = new X;
f(*px, *px);
delete px;
return 0;
}
//13.14
#include <iostream>
class numbered {
public:
numbered()
{
static int unique = 0;
mysn = unique++;
}
int mysn;
};
void f(numbered s)
{
std::cout << s.mysn << std::endl;
}
int main()
{
numbered a, b = a, c = b;
f(a);
f(b);
f(c);
}
//13.15
#include <iostream>
class numbered {
public:
numbered()
{
static int unique = 0;
mysn = unique++;
}
numbered(const numbered& n) { mysn = n.mysn + 1; }
int mysn;
};
void f(numbered s)
{
std::cout << s.mysn << std::endl;
}
int main()
{
numbered a, b = a, c = b;
f(a);
f(b);
f(c);
}
//13.16
#include <iostream>
class numbered {
public:
numbered()
{
static int unique = 0;
mysn = unique++;
}
numbered(const numbered& n) { mysn = n.mysn + 1; }
int mysn;
};
void f(const numbered& s)
{
std::cout << s.mysn << std::endl;
}
int main()
{
numbered a, b = a, c = b;
f(a);
f(b);
f(c);
}
//13.19
class Employee
{
public:
Employee();//默认构造函数
Employee(string& s);//接受一个string的构造函数
Employee(const Employee&) = delete;//不需要拷贝构造函数,怎么可能有人一样。将其声明为 =delete
Employee& operator= (const Employee&) = delete;
int number() { return _number; }
private:
string employee;
int _number;
static int O_number;//static静态成员数据在类内声明,但只可以在类外定义,在类外定义时可不加static
};
//13.20
#include<iostream>
#include<string>
using namespace std;
//具体操作时将类的声明置于头文件中
class Employee
{
public:
Employee();//默认构造函数
Employee(string& s);//接受一个string的构造函数
Employee(const Employee&) = delete;//不需要拷贝构造函数,怎么可能有人一样。将其声明为 =delete
Employee& operator= (const Employee&) = delete;
int number() { return _number; }
private:
string employee;
int _number;
static int O_number;//static静态成员数据在类内声明,但只可以在类外定义,在类外定义时可不加static
};
int Employee::O_number = 0;
Employee::Employee()//默认构造函数
{
_number = O_number++;
}
Employee::Employee(string& s)//接受一个string的构造函数
{
employee = s;
_number = O_number++;
}
void show(Employee &a)
{
cout << a.number() << endl;
}
int main()
{
Employee a, b, c;
show(a);//调用函数时需要拷贝一次
show(b);
show(c);
return 0;
}
//13.20
TextQuery和QueryResult的所有成员都将被拷贝。
//13.21
不需要自己定义拷贝成员函数。判断是否需要定义自己的拷贝成员函数首先应该判断是否自己需要定义析构函数,因为这两个类都有自己的动态指针,因此不需要析构,所以其可直接=default即可
//13.22
#pragma once
#include<string>
using namespace std;
class HasPtr {
public:
HasPtr();//默认构造函数
//拷贝构造函数
HasPtr(const HasPtr&s) :ps(new string(*s.ps)), i(s.i) {}
//拷贝复制构造函数
HasPtr& operator=(const HasPtr&s)
{
auto n_ps = new string(*s.ps);
delete ps;
ps = n_ps;
i = s.i;
return *this;
}
//析构函数
~HasPtr(){delete ps;}
private:
string *ps;
int i;
};
//13.26
#pragma once
#include <vector>
#include <string>
#include <initializer_list>
#include <memory>
#include <exception>
using std::vector;
using std::string;
class ConstStrBlobPtr;
class StrBlob {
public:
using size_type = vector<string>::size_type;
friend class ConstStrBlobPtr;
ConstStrBlobPtr begin() const;
ConstStrBlobPtr end() const;
StrBlob() : data(std::make_shared<vector<string>>()) {}
StrBlob(std::initializer_list<string> il)
: data(std::make_shared<vector<string>>(il))
{
}
// copy constructor
StrBlob(const StrBlob& sb)
: data(std::make_shared<vector<string>>(*sb.data))
{
}
// copyassignment operators
StrBlob& operator=(const StrBlob& sb);
size_type size() const { return data->size(); }
bool empty() const { return data->empty(); }
void push_back(const string& t) { data->push_back(t); }
void pop_back()
{
check(0, "pop_back on empty StrBlob");
data->pop_back();
}
std::string& front()
{
check(0, "front on empty StrBlob");
return data->front();
}
std::string& back()
{
check(0, "back on empty StrBlob");
return data->back();
}
const std::string& front() const
{
check(0, "front on empty StrBlob");
return data->front();
}
const std::string& back() const
{
check(0, "back on empty StrBlob");
return data->back();
}
private:
void check(size_type i, const string& msg) const
{
if (i >= data->size()) throw std::out_of_range(msg);
}
private:
std::shared_ptr<vector<string>> data;
};
class ConstStrBlobPtr {
public:
ConstStrBlobPtr() : curr(0) {}
ConstStrBlobPtr(const StrBlob& a, size_t sz = 0) : wptr(a.data), curr(sz) {} // should add const
bool operator!=(ConstStrBlobPtr& p) { return p.curr != curr; }
const string& deref() const
{ // return value should add const
auto p = check(curr, "dereference past end");
return (*p)[curr];
}
ConstStrBlobPtr& incr()
{
check(curr, "increment past end of StrBlobPtr");
++curr;
return *this;
}
private:
std::shared_ptr<vector<string>> check(size_t i, const string& msg) const
{
auto ret = wptr.lock();
if (!ret) throw std::runtime_error("unbound StrBlobPtr");
if (i >= ret->size()) throw std::out_of_range(msg);
return ret;
}
std::weak_ptr<vector<string>> wptr;
size_t curr;
};
#include<iostream>
#include<string>
#include"HasPtr.h"
using namespace std;
ConstStrBlobPtr StrBlob::begin() const // should add const
{
return ConstStrBlobPtr(*this);
}
ConstStrBlobPtr StrBlob::end() const // should add const
{
return ConstStrBlobPtr(*this, data->size());
}
StrBlob& StrBlob::operator=(const StrBlob& sb)
{
data = std::make_shared<vector<string>>(*sb.data);
return *this;
}
//13.27
class HasPtr {
public:
HasPtr(const string &s = string()) :ps(new string(s)), i(1), use(new size_t(1)) {}
HasPtr(const HasPtr &p) :ps(p.ps), i(p.i), use(p.use) {}
HasPtr &operator=(const HasPtr&);
~HasPtr();
private:
string *ps;
int i;
size_t *use;
};
HasPtr::~HasPtr()
{
if (--*use)
{
delete ps;
delete use;
}
}
HasPtr& HasPtr::operator=(const HasPtr &rhs)
{
++*rhs.use;
if (--*use == 0)
{
delete ps;
delete use;
}
ps = rhs.ps;
i = rhs.i;
use = rhs.use;
return *this;
}
//13.28
#include <string>
using std::string;
class TreeNode {
public:
TreeNode()
: value(string()), count(new int(1)), left(nullptr), right(nullptr)
{
}
TreeNode(const TreeNode& rhs)
: value(rhs.value), count(rhs.count), left(rhs.left), right(rhs.right)
{
++*count;
}
TreeNode& operator=(const TreeNode& rhs);
~TreeNode()
{
if (--*count == 0) {
if (left) {
delete left;
left = nullptr;
}
if (right) {
delete right;
right = nullptr;
}
delete count;
count = nullptr;
}
}
private:
std::string value;
int* count;
TreeNode* left;
TreeNode* right;
};
class BinStrTree {
public:
BinStrTree() : root(new TreeNode()) {}
BinStrTree(const BinStrTree& bst) : root(new TreeNode(*bst.root)) {}
BinStrTree& operator=(const BinStrTree& bst);
~BinStrTree() { delete root; }
private:
TreeNode* root;
};
TreeNode& TreeNode::operator=(const TreeNode& rhs)
{
++*rhs.count;
if (--*count == 0) {
if (left) {
delete left;
left = nullptr;
}
if (right) {
delete right;
right = nullptr;
}
delete count;
count = nullptr;
}
value = rhs.value;
left = rhs.left;
right = rhs.right;
count = rhs.count;
return *this;
}
BinStrTree& BinStrTree::operator=(const BinStrTree& bst)
{
TreeNode* new_root = new TreeNode(*bst.root);
delete root;
root = new_root;
return *this;
}
//13.29
因为函数中调用的swap是std::swap中的swap,和swap(HasPtr&rhs,HasPtr &lhs)不一样
//13.30
#pragma once
#include <string>
#include <iostream>
using namespace std;
class HasPtr {
public:
friend void swap(HasPtr&, HasPtr&);
HasPtr(const std::string& s = std::string()) : ps(new std::string(s)), i(0)
{
}
HasPtr(const HasPtr& hp) : ps(new std::string(*hp.ps)), i(hp.i) {}
HasPtr& operator=(const HasPtr& hp)
{
auto new_p = new std::string(*hp.ps);
delete ps;
ps = new_p;
i = hp.i;
return *this;
}
~HasPtr() { delete ps; }
void show() { std::cout << *ps << std::endl; }
private:
std::string* ps;
int i;
};
void swap(HasPtr& lhs, HasPtr& rhs)
{
using std::swap;
swap(lhs.ps, rhs.ps);
swap(lhs.i, rhs.i);
std::cout << "call swap(HasPtr& lhs, HasPtr& rhs)" << std::endl;
}
#include"HasPtr.h"
using namespace std;
int main()
{
string s1 = "I am", s2 = "a boy";
HasPtr h1(s1),h2(s2),h3("a bad boy");
swap(h1, h2);
h1.show();
h2.show();
h3.show();
return 0;
}
//13.31
#pragma once
#include<iostream>
#include<string>
#include<vector>
using namespace std;
class HasPtr {
public:
friend void swap(HasPtr&, HasPtr&);
friend bool operator<(const HasPtr& lhs, const HasPtr& rhs);
friend void show(vector<HasPtr>& vec);
HasPtr(const std::string& s = std::string()) : ps(new std::string(s)), i(0)
{
}
HasPtr(const HasPtr& hp) : ps(new std::string(*hp.ps)), i(hp.i) {}
HasPtr& operator=(HasPtr tmp)
{
this->swap(tmp);
return *this;
}
~HasPtr() { delete ps; }
void swap(HasPtr& rhs)
{
using std::swap;
swap(ps, rhs.ps);
swap(i, rhs.i);
std::cout << "call swap(HasPtr &rhs)" << std::endl;
}
private:
std::string* ps;
int i;
};
void swap(HasPtr& lhs, HasPtr& rhs)
{
lhs.swap(rhs);
}
bool operator<(const HasPtr& lhs, const HasPtr& rhs)
{
return *lhs.ps < *rhs.ps;
}
void show(vector<HasPtr>& vec)
{
vector<HasPtr>::iterator it1 = vec.begin();
for (it1; it1 != vec.end(); ++it1)
{
cout << *(it1->ps) << endl;
}
}
#include"HasPtr.h"
#include<algorithm>
#include<vector>
using namespace std;
int main()
{
vector<HasPtr> vec1;
HasPtr a("l");
HasPtr b("llll");
HasPtr c("lll");
vec1.push_back(a);
vec1.push_back(b);
vec1.push_back(c);
vector<HasPtr>::iterator it1 = vec1.begin();
sort(vec1.begin(), vec1.end());
show(vec1);
return 0;
}
//13.33
我们的目的是对传入的folder进行修改,传值的方式会使得我们修改的是其副本,const修饰符使得我们不能对其进行修改。所以都不行
//13.34-37
#pragma once
#include <set>
#include <string>
class Folder;
class Message {
friend void swap(Message&, Message&);
friend void swap(Folder&, Folder&);
friend class Folder;
public:
explicit Message(const std::string& str = "") : contents(str) {}//直接初始化
Message(const Message&);//拷贝构造函数
Message& operator=(const Message&);//拷贝复制构造函数
~Message();
void save(Folder&);
void remove(Folder&);
void print_debug();
private:
std::string contents;
std::set<Folder*> folders;
void add_to_Folders(const Message&);//将新的message添加到folders中
void remove_from_Folders();
void addFldr(Folder* f) { folders.insert(f); }
void remFldr(Folder* f) { folders.erase(f); }
};
void swap(Message&, Message&);
class Folder {
friend void swap(Message&, Message&);
friend void swap(Folder&, Folder&);
friend class Message;
public:
Folder() = default;
Folder(const Folder&);
Folder& operator=(const Folder&);
~Folder();
void print_debug();
private:
std::set<Message*> msgs;
void add_to_Messages(const Folder&);
void remove_from_Messages();
void addMsg(Message* m) { msgs.insert(m); }
void remMsg(Message* m) { msgs.erase(m); }
};
void swap(Folder&, Folder&);
void swap(Message& lhs, Message& rhs)
{
using std::swap;
lhs.remove_from_Folders();
rhs.remove_from_Folders();
swap(lhs.folders, rhs.folders);
swap(lhs.contents, rhs.contents);
lhs.add_to_Folders(lhs);
rhs.add_to_Folders(rhs);
}
// Message Implementation
Message::Message(const Message& m) : contents(m.contents), folders(m.folders)
{
add_to_Folders(m);
}
Message& Message::operator=(const Message& rhs)
{
remove_from_Folders();
contents = rhs.contents;
folders = rhs.folders;
add_to_Folders(rhs);
return *this;
}
Message::~Message()
{
remove_from_Folders();
}
void Message::save(Folder& f)
{
addFldr(&f);
f.addMsg(this);
}
void Message::remove(Folder& f)
{
remFldr(&f);
f.remMsg(this);
}
void Message::print_debug()
{
std::cout << contents << std::endl;
}
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);
}
// Folder Implementation
void swap(Folder& lhs, Folder& rhs)
{
using std::swap;
lhs.remove_from_Messages();
rhs.remove_from_Messages();
swap(lhs.msgs, rhs.msgs);
lhs.add_to_Messages(lhs);
rhs.add_to_Messages(rhs);
}
Folder::Folder(const Folder& f) : msgs(f.msgs)
{
add_to_Messages(f);
}
Folder& Folder::operator=(const Folder& rhs)
{
remove_from_Messages();
msgs = rhs.msgs;
add_to_Messages(rhs);
return *this;
}
Folder::~Folder()
{
remove_from_Messages();
}
void Folder::print_debug()
{
for (auto m : msgs) std::cout << m->contents << " ";
std::cout << std::endl;
}
void Folder::add_to_Messages(const Folder& f)
{
for (auto m : f.msgs) m->addFldr(this);
}
void Folder::remove_from_Messages()
{
for (auto m : msgs) m->remFldr(this);
}
#include <iostream>
#include"HasPtr.h"
int main()
{
Message firstMail("hello");
Message signInMail("welcome to cppprimer");
Folder mailBox;
firstMail.print_debug(); // 输出: "hello"
firstMail.save(mailBox); // 发送到 mailBox
mailBox.print_debug(); // 输出: "hello"
signInMail.print_debug(); // 输出 "welcome to cppprimer"
signInMail.save(mailBox); // 发送到mailBox
mailBox.print_debug(); // 输出 "welcome to cppprimer hello"
firstMail = firstMail; //
firstMail.print_debug(); // 输出 "hello"
mailBox.print_debug(); // 输出"welcome to cppprimer hello"
}
//13.39
#include <memory>
#include <string>
class StrVec {
public:
StrVec() : elements(nullptr), first_free(nullptr), cap(nullptr) {}
StrVec(const StrVec&);
StrVec& operator=(const StrVec&);
~StrVec();
void push_back(const std::string&);
size_t size() const { return first_free - elements; }
size_t capacity() const { return cap - elements; }
std::string* begin() const { return elements; }
std::string* end() const { return first_free; }
void reserve(size_t new_cap);
void resize(size_t count);
void resize(size_t count, const std::string&);
private:
std::pair<std::string*, std::string*> alloc_n_copy(const std::string*,
const std::string*);
void free();
void chk_n_alloc()
{
if (size() == capacity()) reallocate();
}
void reallocate();
void alloc_n_move(size_t new_cap);
private:
std::string* elements;
std::string* first_free;
std::string* cap;
std::allocator<std::string> alloc;
};
void StrVec::push_back(const std::string& s)
{
chk_n_alloc();
alloc.construct(first_free++, s);
}
std::pair<std::string*, std::string*> StrVec::alloc_n_copy(const std::string* b,
const std::string* e)
{
auto data = alloc.allocate(e - b);
return{ data, std::uninitialized_copy(b, e, data) };
}
void StrVec::free()
{
if (elements) {
for (auto p = first_free; p != elements;) alloc.destroy(--p);
alloc.deallocate(elements, cap - elements);
}
}
StrVec::StrVec(const StrVec& rhs)
{
auto newdata = alloc_n_copy(rhs.begin(), rhs.end());
elements = newdata.first;
first_free = cap = newdata.second;
}
StrVec::~StrVec()
{
free();
}
StrVec& StrVec::operator=(const StrVec& rhs)
{
auto data = alloc_n_copy(rhs.begin(), rhs.end());
free();
elements = data.first;
first_free = cap = data.second;
return *this;
}
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);
}
}
//13.47
String(const String& rhs)//拷贝构造函数
{
range_initializer(rhs.elements, rhs.end);
cout << "拷贝构造函数" << endl;
}
String& operator=(const String& rhs)//拷贝赋值运算符
{
auto newstr = alloc_n_copy(rhs.elements, rhs.end);
free();
elements = newstr.first;
end = newstr.second;
cout << "拷贝赋值运算符" << endl;
return *this;
}
//13.48
#include <iostream>
#include <vector>
#include "StrVec.h"
using namespace std;
int main(int argc, char**argv)
{
vector<String> vec;
String s1("hello");
String s2 = s1;
vec.push_back(s1);
vec.push_back(s2);
return 0;
}
//13.55
void push_back(string &&s) { data->push_back(move(s)); }
//13.58
#include <vector>
#include <iostream>
#include <algorithm>
using std::vector;
using std::sort;
class Foo {
public:
Foo sorted() && ;
Foo sorted() const&;
private:
vector<int> data;
};
Foo Foo::sorted() &&
{
sort(data.begin(), data.end());
std::cout << "&&" << std::endl; // debug
return *this;
}
Foo Foo::sorted() const &
{
std::cout << "const &" << std::endl; // debug
return Foo(*this).sorted(); //13.57
}
int main()
{
Foo().sorted(); // call "&&"
Foo f;
f.sorted(); // call "const &"
}