13.1 拷贝、赋值与销毁
13.1.1拷贝构造函数
拷贝构造函数条件:
1. 第一个参数为自身类型的引用
2. 任何额外参数都有默认值
对于类类型的成员,会使用其拷贝构造函数来拷贝,内置类型则直接拷贝。
#include <bits/stdc++.h>
using namespace std;
int main()
{
return 0;
}
class Sales_data {
public:
//拷贝析构函数
Sales_data(const Sales_data &);
private:
string bookNo;
int units_sold = 0;
double revenue;
};
Sales_data::Sales_data(const Sales_data &orig):
bookNo(orig.bookNo),
units_sold(orig.units_sold),
revenue(orig.revenue)
{ }
拷贝初始化使用:
1. =号赋值
2. 非引用类型参数传递
3. 返回一个非引用类型对象
4. 花括号列表初始化数组、聚合类
5. 类类型对其分配的对象初始化。push 、insert
explicit构造函数:其只能用于直接初始化,其他情况不能隐式的使用。
拷贝赋值运算符:
会将右侧值通过成员类型的拷贝赋值运算符对成员进行赋值,然后返回左侧运算对象的引用。
Sales_data& Sales_data::operator=(const Sales_data &rhs) {
bookNo = rhs.bookNo;
units_sold = rhs.units_sold;
revenue = rhs.revenue;
return *this;
}
13.2 拷贝控制和资源管理
一但一个类需要析构函数,那么它几乎肯定也需要一个拷贝构造函数和一个拷贝赋值运算符。
为定义这些函数,我们
#include <bits/stdc++.h>
using namespace std;
class Folder;
class Message {
friend void swap(Message& ,Message&);
friend class Folder;
public:
explicit Message(const string &str = ""):
contents(str){}
Message(const Message&);
Message& operator=(const Message&);
~Message();
void save(Folder &f);
void remove(Folder &f);
void debug_print();
private:
string contents;
set<Folder*> folders;
void add_to_Folders(const Message&);
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 class Message;
public:
~Folder();
Folder(const Folder&);
Folder&operator=(const Folder&);
// Folder(Folder&&);
// Folder&operator=(Folder&&);
Folder()= default;
void save(Message&);
void remove(Message&);
void debug_print();
private:
set<Message*> msgs;
void add_to_Messages(const Folder&);
void remove_from_Msgs();
void addMsg(Message *m){msgs.insert(m);}
void remMsg(Message *m){msgs.erase(m);}
// void move_Messages(Folder*);
};
/*message -> floder*/
void Folder::add_to_Messages(const Folder &f) {
for(auto msg : f.msgs)
msg->addFldr(this);
}
/*all msg - this folder*/
void Folder::remove_from_Msgs() {
while(!msgs.empty())
{
(*msgs.begin())->remove(*this);
}
}
Folder::Folder(const Folder &m) :
msgs(m.msgs)
{
add_to_Messages(m);
}
//拷贝赋值运算符
Folder& Folder::operator=(const Folder &rhs) {
remove_from_Msgs();
msgs = rhs.msgs;
add_to_Messages(rhs);
}
//析构函数
Folder::~Folder() {
remove_from_Msgs();
}
/*fold -> message , message -> fold*/
void Folder::save(Message &m) {
msgs.insert(&m);
m.addFldr(this);
}
/*fold - message ,message - fold*/
void Folder::remove(Message &m) {
msgs.erase(&m);
m.remFldr(this);
}
void Folder::debug_print() {
cerr<<"there are "<<msgs.size()<<"message in this folder."<<endl;
}
/*************************************/
/*message->folder, folder->message*/
void Message::save(Folder &f) {
folders.insert(&f);
f.addMsg(this);
}
/*message - folder , folder - message*/
void Message::remove(Folder &f) {
folders.erase(&f);
f.remMsg(this);
}
/*all folder -> message*/
void Message::add_to_Folders(const Message &m) {
for(auto f:m.folders)
{
f->addMsg(this);
}
}
//remove this Message
/*all folder - message*/
void Message::remove_from_Folders() {
for(auto f : folders)
f->remMsg(this);
}
Message::Message(const Message &m):
contents(m.contents),folders(m.folders)
{
/*把this添加到对应folder中*/
add_to_Folders(m);
}
//从所有的message删除
Message::~Message() {
remove_from_Folders();
}
Message& Message::operator=(const Message &rhs){
// delete *this
remove_from_Folders();
contents = rhs.contents;
folders = rhs.folders;
/*add this to folders*/
add_to_Folders(rhs);
return *this;
}
void Message::debug_print() {
cerr << "Message\t"<<contents<<endl;
cerr<<"Appers in" << folders.size()<<" Folders"<<endl;
}
void swap(Message &lhs, Message &rhs)
{
for(auto f : lhs.folders)
f->remMsg(&lhs);
for(auto f : rhs.folders)
f->remMsg(&rhs);
swap(lhs.folders,rhs.folders);
swap(lhs.contents,rhs.contents);
for(auto f : lhs.folders)
f->addMsg(&lhs);
for(auto f : rhs.folders)
f->addMsg(&rhs);
}
int main() {
string s1("contents1");
string s2("contents2");
string s3("contents3");
string s4("contents4");
string s5("contents5");
string s6("contents6");
Message m1(s1);
Message m2(s2);
Message m3(s3);
Message m4(s4);
Message m5(s5);
Message m6(s6);
Folder f1;
Folder f2;
m1.save(f1); m3.save(f1); m5.save(f1);
// m1.debug_print();
// m2.debug_print();
// f1.debug_print();
/*m1,m3,m5*/
Message c1(m1);
Message c2(m3);
// m1.debug_print();
// f2.debug_print();
// m1,m3,m5,c1,c2
// f1.debug_print();
m1 = m5;
swap(m1,m4);
//m5,m3,m5,c1,c2
m1.debug_print();
f1.debug_print();
return 0;
}