Prev: pros and cons of returning const ref to string instead of string by value
Next: unique id (uid, uuid, guid etc) class needed
From: muler on 9 Dec 2009 06:04 Consider this: T& T::operator=(const T& other) { if(this != &other) { // the below code destroys *this, right? // but are we not committing a suicide? - // destroying *this inside (*this).operator= ?? this->~T(); new (this) T(other); } return *this; } Thanks! -- [ See http://www.gotw.ca/resources/clcm.htm for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ]
From: Chris Uzdavinis on 9 Dec 2009 18:32 On Dec 9, 5:04 pm, muler <mulugeta.abe...(a)gmail.com> wrote: > Consider this: > > T& T::operator=(const T& other) > { > if(this != &other) > { > // the below code destroys *this, right? > // but are we not committing a suicide? - > // destroying *this inside (*this).operator= ?? > this->~T(); > > new (this) T(other); > } > return *this; > > } This anti-pattern is covered at length in Herb Sutter's book Exceptional C++, but the article of GotW is available online. Please read it. :) http://www.gotw.ca/gotw/023.htm Summary: bad! bad! bad! Don't do it! (And take a shower after even thinking about it.) Chris -- [ See http://www.gotw.ca/resources/clcm.htm for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ]
From: Goran on 9 Dec 2009 18:32 On Dec 10, 12:04 am, muler <mulugeta.abe...(a)gmail.com> wrote: > Consider this: > > T& T::operator=(const T& other) > { > if(this != &other) > { > // the below code destroys *this, right? > // but are we not committing a suicide? - > // destroying *this inside (*this).operator= ?? > this->~T(); > > new (this) T(other); > } > return *this; > > } > > Thanks! > { edits: quoted banner removed. please don't quote the banner. -mod } This is 100% horrible code. This is code that would be written by someone who understands C more or less well, but does not understand C+ +. Yes, this is possible, and it's possible to work, but suffers from a following problem: if constructor throws, this is not fully constructed, but "reachable" (there are references to it in the code). Depending on the situation, that might be more or less dangerous. Even worse situation is if T has virtual methods and a base class, and a base constructor throws - in usual implementations, that leaves T's virtual table broken, which is a disaster waiting to happen. Destructor should almost never be called explicitly. Correct solution could be to tun things around and write copy constructor in terms of operator=. Or to replace this->~T(); new (this) T(other) with a copy function and use that in both copy constructor and assignment operator. But none of that should be done unless performance profiling shows that there's an issue in just having the most usual implementations (= copies membes, copy ctor uses initialization list). Or if people working on the code are just plain stupid and/or lazy and can't remember, or be bothered, to keep two places in check. Goran. -- [ See http://www.gotw.ca/resources/clcm.htm for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ]
From: Mathias Gaunard on 9 Dec 2009 20:41 On 9 d�c, 23:04, muler <mulugeta.abe...(a)gmail.com> wrote: > Consider this: > > T& T::operator=(const T& other) > { > if(this != &other) > { > // the below code destroys *this, right? > // but are we not committing a suicide? - > // destroying *this inside (*this).operator= ?? > this->~T(); > > new (this) T(other); > } > return *this; > > } In any case, it's a bad idea since if new (this) T(other) throws, you're screwed. The recommended way to write operator= is void T::swap(T& other) { using std::swap; swap(member1, other.member1); swap(member2, other.member2); ... swap(memberN, other.memberN); } T& T::operator=(T other) { swap(other); return *this; } -- [ See http://www.gotw.ca/resources/clcm.htm for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ]
From: Taras Shevchuk on 9 Dec 2009 20:40
On 10.12.2009 1:04, muler wrote: > Consider this: > > T& T::operator=(const T& other) > { > if(this !=&other) > { > // the below code destroys *this, right? > // but are we not committing a suicide? - > // destroying *this inside (*this).operator= ?? > this->~T(); > > new (this) T(other); > } > return *this; > } > > Thanks! > I see following problems with your implementation: 1. object *this will be in inconsistent state in case if "new (this) T(other);" generates exception; 2. in case if T is base class then "this->~T();" will partially delete object. The common pattern for assignment operation is following: T& T::operator=(const T& other) { T tmp = other; swap(tmp); return *this; } -- [ See http://www.gotw.ca/resources/clcm.htm for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ] |