gpt4 book ai didi

c++ - 消息分配运算符不使用交换

转载 作者:行者123 更新时间:2023-11-30 05:41:12 28 4
gpt4 key购买 nike

抱歉,如果标题有点偏离,不知道该用什么。

所以在这本书(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 让我知道链接。

链接:https://github.com/Mooophy/Cpp-Primer

关于c++ - 消息分配运算符不使用交换,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31260733/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com