I have this text from C++ primer 5th edition. ch 19.6 Union:
class Token { public: Token(): tok(INT), ival{0} { } Token(const Token &t): tok(t.tok) { copyUnion(t); } Token &operator=(const Token&); ~Token() { if (tok == STR) sval.~string(); } Token &operator=(const std::string&); Token &operator=(char); Token &operator=(int); Token &operator=(double); private: enum {INT, CHAR, DBL, STR} tok; // discriminant union { // anonymous union char cval; int ival; double dval; std::string sval; }; // each Token object has an unnamed member of this unnamed union type // check the discriminant and copy the union member as appropriate void copyUnion(const Token&); }; Token &Token::operator=(const std::string &s) { if (tok == STR) // if we already hold a string, just do an assignment sval = s; else new(&sval) string(s); // otherwise construct a string tok = STR; // update the discriminant return *this; }In this case, if the union already holds a string, we can use the normal string assignment operator to give a new value to that string. Otherwise, there is no existing string object on which to invoke the string assignment operator. Instead, we must construct a string in the memory that holds the union. We do so using placement new (§ 19.1.2, p. 824) to construct a string at the location in which
svalresides. We initialize that string as a copy of our string parameter. We next update the discriminant and return.
Everything is so straightforward for me but what confuses me is this version of the copy-assignment operator (that takes an std::string): and the last paragraph: "if the union already holds a string..." But in case the union doesn't hold a string then why we bother to use such placement new? as long as the assignment operator calls the destructor thus destroys the object then frees memory which is the reverse of the constructor?
I mean why he didn't directly write this?
sval = s;
I think there's no need to call the dtor explicitly with sval.~string() because the assignment operator does that instead. I mean no condition is required.