抱歉,如果标题有点偏离,不知道该用什么。
所以在这本书(C++ 入门第 5 版)中,我正在学习 C++,我遇到了一个问题:
We did not use copy and swap to define the Message assignment operator. Why do you suppose this is so?
我真的不知道,因为即使在分配同一个对象 t 本身时,两者也会产生相同的结果。
两个文件的 main.cpp:
#include <iostream>
#include "Folder.hpp"
#include "Message.hpp"
int main()
{
Message m("Hello");
Folder f1, f3;
m.save(f1);
Message m2;
m2 = m;
m2.save(f3);
m2.save(f1);
std::cout << f3.msgs.size() << std::endl;
std::cout << f1.msgs.size() << std::endl;
return 0;
}
交换功能:
void swap(Message &lhs, Message &rhs)
{
using std::swap;
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);
}
不使用交换
operator=:
Message& Message::operator=(const Message &rhs)
{
remove_from_Folders();
contents = rhs.contents;
folders = rhs.folders;
add_to_Folders(rhs);
return *this;
}
使用交换进行更改:
消息.hpp Message& operator=(Message);//匹配 def 的新声明
消息.cpp
Message& Message::operator=(Message rhs)
{
swap(*this, rhs);
return *this;
}
输出是
2
1
两个版本都符合预期。
我真的不知道不使用 swap 的好处是什么,除了需要做的工作会少一些。
类:
// Message.hpp
#ifndef MESSAGE_HPP
#define MESSAGE_HPP
#include <string>
#include <set>
class Folder;
class Message
{
friend class Folder;
friend void swap(Message&, Message&);
friend std::ostream& print(std::ostream &os, const Message &m);
public:
explicit Message(const std::string &str = "") : contents(str) { }
~Message();
Message(const Message&);
Message& operator=(const Message&);
void save(Folder&);
void remove(Folder&);
private:
std::string contents;
std::set<Folder*> folders;
void add_to_Folders(const Message&);
void remove_from_Folders();
};
std::ostream& print(std::ostream &, const Message &);
#endif
// Message.cpp
#include "Message.hpp"
#include "Folder.hpp"
void swap(Message &lhs, Message &rhs)
{
using std::swap;
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);
}
void Message::save(Folder &f)
{
folders.insert(&f);
f.addMsg(this);
}
void Message::remove(Folder &f)
{
folders.erase(&f);
f.remMsg(this);
}
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);
folders.clear();
}
Message::~Message()
{
remove_from_Folders();
}
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;
}
std::ostream& print(std::ostream &os, const Message &m)
{
os << m.contents;
return os;
}
// Folder.hpp
#ifndef FOLDER_HPP
#define FOLDER_HPP
#include <ostream>
#include <set>
class Message;
class Folder
{
friend class Message;
friend std::ostream& print(std::ostream &, Folder &);
public:
~Folder();
void addMsg(Message *);
void remMsg(Message *);
private:
std::set<Message*> msgs;
};
std::ostream& print(std::ostream &, Folder &);
#endif
// Folder.cpp
#include "Folder.hpp"
#include "Message.hpp"
Folder::~Folder()
{
for (auto &m : msgs)
{
m->remove(*this);
}
}
void Folder::addMsg(Message *m)
{
msgs.insert(m);
}
void Folder::remMsg(Message *m)
{
msgs.erase(m);
}
std::ostream& print(std::ostream &os, Folder &f)
{
for (const auto &m : f.msgs)
{
print(os, *m) << std::endl;
}
return os;
}
干杯
最佳答案
所以@KeithSmith 发布了一个指向答案的链接,我从那里得到了两个。他们在这里:
Exercise 13.38:
We did not use copy and swap to define the Message assignment operator. Why do you suppose this is so?
@Mooophy copy-and-swap 是一种优雅的方式 动态分配的内存。在 Message 类中,没有分配任何内容 动态地。因此,使用这个习语没有任何意义,而且会成功 由于指向后方的指针,实现起来更加复杂。
@pezy 在这种情况下,
swap
函数是特殊的。会清楚二Message
的文件夹,然后交换成员,并将自己添加到每个 文件夹。但是,Message
赋值运算符只是清除自身,并且 复制成员,并将自己添加到每个文件夹中。rhs
没有 需要清除并添加到文件夹。所以,如果使用 copy-and-swap define,效率会很低。
基本上 Mooophy 是说 copy-and-swap 是用于动态分配内存的东西,而 Message 类没有动态分配内存。
pezy 说 swap 是不同的,它 swap 将 lhs 和 rhs 添加到每个文件夹,而赋值运算符只添加 lhs,这样效率更高。
只是想感谢 KeithSmith 让我知道链接。
关于c++ - 消息分配运算符不使用交换,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31260733/