【问题标题】:Protection again self-assignment保护再自分配
【发布时间】:2015-06-01 05:16:34
【问题描述】:

我正在阅读有关复制控制的内容,并在 C++ Primer(第 13.4 章)一书中看到了以下示例。

我的问题是关于 remove_from_Folders(); 内部复制赋值运算符:
如果我们先做remove_from_Folders();,在自赋值的情况下,它的folders.clear();是不是会清除rhs的数据成员导致失败?

Message& Message::operator=(const Message &rhs)
{
 // handle self-assignment by removing pointers before inserting them
 remove_from_Folders();  // update existing Folders
 contents = rhs.contents; // copy message contents from rhs
 folders = rhs.folders;  // copy Folder pointers from rhs
 add_to_Folders(rhs);  // add this Message to those Folders
 return *this;
}

// remove this Message from the corresponding Folders
void Message::remove_from_Folders()
{
 for (auto f : folders) // for each pointer in folders
     f->remMsg(this);  // remove this Message from that Folder
 folders.clear();
}

类定义为:

class Message {
 friend class Folder;
public:
 // folders is implicitly initialized to the empty set
 explicit Message(const std::string &str = ""):
 contents(str) { }
 // copy control to manage pointers to this Message
 Message(const Message&);  // copy constructor
 Message& operator=(const Message&); // copy assignment
 ~Message();  // destructor
 // add/remove this Message from the specified Folder's set of messages
 void save(Folder&);
 void remove(Folder&);
private:
 std::string contents;  // actual message text
 std::set<Folder*> folders; // Folders that have this Message
 // utility functions used by copy constructor, assignment, and destructor
 // add this Message to the Folders that point to the parameter
 void add_to_Folders(const Message&);
 // remove this Message from every Folder in folders
 void remove_from_Folders();
};

【问题讨论】:

  • 是的,如果发生自赋值,赋值运算符似乎会按照你说的做。对我来说看起来像一个错误,尽管有源评论。
  • 简单的方法;创建一个临时副本和交换(这也是异常安全的)
  • 这似乎是copy and swap 的好候选
  • 我正在阅读同一本书,刚刚进入复制控制章节。我也在问自己同样的问题。所以这是一个错误,不是吗?

标签: c++ assignment-operator


【解决方案1】:

https://github.com/Mooophy/Cpp-Primer/tree/master/ch13

上面列出的示例代码更适合处理 operator=(self)

Message& Message::operator=(const Message &rhs) {
    if (this != &rhs) { // self-assigment check is necessary
                        // while remove_from_Folders() do folders.clear()
        remove_from_Folders();    // update existing Folders
        contents = rhs.contents;  // copy message contents from rhs
        folders = rhs.folders;    // copy Folder pointers from rhs
        add_to_Folders(rhs);      // add this Message to those Folders
    } 
    return *this;
}

【讨论】:

  • 有人可以解释为什么这个答案被否决了吗?如果有人想将 folders.clear() 保留在 remove_from_Folders() 中,它很简短,不言自明,只添加一行代码对 Message 类的修改会使情况复杂化。
猜你喜欢
  • 1970-01-01
  • 2019-09-30
  • 2013-03-24
  • 2017-02-05
  • 2012-06-14
  • 1970-01-01
  • 1970-01-01
  • 2012-09-05
  • 2011-09-04
相关资源
最近更新 更多