1. 基本操作:拷贝、赋值与销毁
- 拷贝构造函数:参数为该类的一个const引用
- 拷贝赋值运算符重载
- 析构函数:由于析构函数不接受参数,因此它不能被重载。
拷贝构造函数和拷贝赋值运算符的不一样在于前者不需要先重置当前对象,而后者需要。原因在于前者是构造函数,本身是没有经过初始化的。
合成xxx函数
编译器帮忙定义的上述三种函数:调用成员(非static)的xxx函数构造该类的xxx函数。
三五法则
- 需要析构函数的类也需要拷贝和赋值操作
- 需要拷贝操作的类也需要赋值操作,反之亦然
阻止拷贝
新标准建议使用 = delete来完成拷贝的相关函数的调用阻止。
2. 拷贝控制和资源管理
- 行为像值的类
每个对象都应该拥有一份自己的拷贝 - 行为像指针的类
类似于自建一个简单的shared_ptr
3. 交换操作
避开std::swap而使用自定义swap的方式
using std::swap;
swap(lhs.h,rhs.h);
//其他的swap
4. 拷贝控制示例类
//Message.h
#pragma once
#include <set>
#include <string>
#include "Folder.h"
using namespace std;
class Message
{
friend class Folder;
public:
explicit Message(const string& str = "") :contents(str) {}//构造函数
Message(const Message&); //拷贝构造函数
Message& operator= (const Message&);//拷贝赋值运算符
~Message();
void save(Folder&);
void remove(Folder&);
private:
string contents;
set<Folder*> folders;
void add_to_folders(const Message&);
void remove_from_folders();
};
//Folder.h
#pragma once
#include "Message.h"
using namespace std;
class Folder
{
friend class Message;
public:
Folder() {}
Folder(const Folder&);
Folder& operator=(const Folder&);
void addMessage(Message&);
void rmMessage(Message&);
~Folder(); //要从保存在本文件夹当中的Message里面删除该Folder
private:
set<Message*> messages;
void tell_message_add(Message*);
void tell_message_rmv(Message*);
};
实现
//Message.cpp
#include "Message.h"
Message::Message(const Message& message):contents(message.contents),folders(message.folders)
{
add_to_folders(*this);
}
Message& Message::operator=(const Message& message)
{
remove_from_folders();
contents = message.contents;
folders = message.folders;
add_to_folders(*this);
return *this;
}
void Message::add_to_folders(const Message& message)
{
for (auto f : message.folders)
f->addMessage(*this);
}
void Message::remove_from_folders()
{
for (auto f : folders)
f->rmMessage(*this);
}
void Message::save(Folder& folder)
{
folders.insert(&folder);
folder.addMessage(*this);
}
void Message::remove(Folder& folder)
{
folders.erase(&folder);
folder.rmMessage(*this);
}
Message::~Message()
{
remove_from_folders();
}
//Folder.cpp
#include "Folder.h"
Folder::Folder(const Folder& folder):messages(folder.messages)
{
for (auto m : folder.messages)
tell_message_add(m);
}
Folder& Folder::operator=(const Folder& folder)
{
for (auto oldM : messages)
tell_message_rmv(oldM);
messages = folder.messages;
for (auto newM : messages)
tell_message_add(newM);
return *this;
}
void Folder::tell_message_add(Message* mPtr)
{
mPtr->folders.insert(this);
}
void Folder::tell_message_rmv(Message* mPtr)
{
mPtr->folders.erase(this);
}
void Folder::addMessage(Message& m)
{
messages.insert(&m);
}
void Folder::rmMessage(Message& m)
{
messages.erase(&m);
}
Folder::~Folder()
{
for (auto oldM : messages)
tell_message_rmv(oldM);
}