Protection again self-assignment
Asked Answered
L

1

6

I was reading about copy-control and came across the following sample in the book C++ Primer (chapter 13.4).

My question is about the remove_from_Folders(); inside copy assignment operator:
If we firstly do remove_from_Folders();, in the case of self assignment, doesn't its folders.clear(); clear the data member of rhs and cause a failure?

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();
}

The class is defined as:

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();
};
Lighter answered 27/3, 2015 at 18:50 Comment(6)
Yes, it appears that the assignment operator will do just what you say in the event of a self-assignment. Looks like a bug to me, the source comment notwithstanding.Knavery
The easy way; create a temporary copy and swap (which is exception safe, also)Chlordane
take a look at this: #3280043Newton
This seems like a good candidate for copy and swapImparity
I'm reading the same book and just got to the copy control chapter. I was asking myself the same question.. so it's a error isn't it?Protrude
I'm reading the chapter currently and immediately started to search for this. The issue was introduced in the first place during the second print of the book and is explained in the errata. From my point of view they have broken the code and not fixed it: ptgmedia.pearsoncmg.com/images/9780321714114/errata/…Neotype
E
1

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

the sampe code listed above is more appropriate for handling 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;
}
Erasion answered 5/7, 2015 at 5:48 Comment(1)
Can somebody explain why this answer was downvoted? It is short, self explanatory and adding only one line of code, if someone wants to keep folders.clear() in remove_from_Folders() this works and keep working even when further modifications to the class Message complicate the situation.Neotype

© 2022 - 2024 — McMap. All rights reserved.