Prev: Conversion of long type to int type
Next: Call for Paper The International Journal of Computer Science (IJCS)
From: Joshua Lehrer on 9 Feb 2010 01:49 I want to overload operator new on my class to take an additional argument. I am therefore required to overload operator delete as well so that if the constructor throws it will call the matching operator delete. I do not want to write additional class specific operator new/delete that take no additional arguments. My problem arises when I attempt to delete the pointer returned from new. As I don't have a "default" operator delete on my class I need to call the operator delete that takes parameters. The only way I can find to do this is to call class::operator delete(pointer,args...); However, this does not call the destructor. So, now I need to explicitly call the destructor and then explicitly call class::operator delete. Is there a syntax to call delete which would pass arguments to the operator delete after calling the destructor? I tried to match the syntax of the call to new and that didn't work: new(new_args) type(constructor_args); delete(delete_args) pointer; Any suggestions? Any explanation why the above doesn't work (other than: the standard doesn't allow it). Why doesn't the standard allow it? e.g.: #include <new> struct foo { //overload operator new void* operator new(size_t, const char *) throw(); //corresponding operator delete to match void operator delete(void *, const char *); //constructor/destrucot foo(int,int); ~foo(); }; void bar() { foo * pfoo = new("hello") foo(1,2); //no appropriate operator delete visible // delete pfoo; //syntax error // delete("goodbye") pfoo; //ugly pfoo->~foo(); foo::operator delete(pfoo,"goodbye"); } -- [ See http://www.gotw.ca/resources/clcm.htm for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ]
From: Andy Venikov on 9 Feb 2010 08:16 Joshua Lehrer wrote: > I want to overload operator new on my class to take an additional > argument. I am therefore required to overload operator delete as well > so that if the constructor throws it will call the matching operator > delete. > > I do not want to write additional class specific operator new/delete > that take no additional arguments. > > My problem arises when I attempt to delete the pointer returned from > new. As I don't have a "default" operator delete on my class I need > to call the operator delete that takes parameters. The only way I can > find to do this is to call class::operator delete(pointer,args...); > However, this does not call the destructor. So, now I need to > explicitly call the destructor and then explicitly call > class::operator delete. > > Is there a syntax to call delete which would pass arguments to the > operator delete after calling the destructor? I tried to match the > syntax of the call to new and that didn't work: > > new(new_args) type(constructor_args); > delete(delete_args) pointer; > Unfortunately, no. Recently I had exactly the same question (see "Why no placement delete?" dated Dec 3rd, 2009) http://groups.google.com/group/comp.lang.c++.moderated/browse_frm/thread/196625d3468b9664/458b3f5c3a1b8828?#458b3f5c3a1b8828 The reasoning is vague. You can find the reasoning line on Bjarn's web-page: <http://www2.research.att.com/~bs/bs_faq2.html#placement-delete> 'The reason that there is no built-in "placement delete" to match placement new is that there is no general way of assuring that it would be used correctly.' -- [ See http://www.gotw.ca/resources/clcm.htm for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ]
From: Dino on 9 Feb 2010 08:16 Josh, Why would you need to pass an argument to your delete call? Just to invoke the correct delete function? I would think that at the time of deletion the class should know how to properly clean itself up (even if the delete was called because of an exception thrown in the constructor). I know you said that you did not want to "write additional class specific operator new/delete that take no additional arguments" but I think this is the way to go, and it can be done without too much excess effort: struct foo { //overload operator new void* operator new(size_t, const char *) throw(); //corresponding operator delete to match void operator delete(void *, const char *); void operator delete(void *); //constructor/destrucot foo(int,int); ~foo(); private: void* operator new(size_t) throw(); }; Now your default operator new cannot be called, and doesn't need to be implemented at all. Meanwhile, define the non-default delete something like this: void foo::operator delete(void * p, const char *) { delete(p); } and define the default delete correctly. Let me know what you think. --Dino -- [ See http://www.gotw.ca/resources/clcm.htm for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ]
From: Joshua Lehrer on 10 Feb 2010 02:28 On Feb 9, 8:16 pm, Dino <dinoch...(a)gmail.com> wrote: > Josh, > > Why would you need to pass an argument to your delete call? Just to > invoke the correct delete function? I would think that at the time of There are a few reasons. First, my question is one of consistency. Why is this legal: new(new_args) type; but not this: delete(delete_args) pointer; especially when writing the new function for the former: void* type::operator new(size_t, args...) throw(); requires you to write the support routine for the latter: void type::operator delete(void *, args...); Second, due to C++ lookup rules, writing a custom operator new now requires you to not only write the proper matching operator delete, but also to write a class specific generic operator delete. Why? Because if you didn't, then a call to delete would fail to find a matching overload. Name resolution would stop at the class level where it finds the first operator delete, the args wouldn't match, and it would fail to compile. So, now, one must write three routines, not just one. :( The reason I want to do it? I have a class than can be created in any number of contexts. I want to be sure that it is created and destroyed by the consumer in the same context. The context is an argument to operator new and operator delete and, in debug mode, we assert that the contexts match. You can think of a context as, perhaps, a thread, and we want to assert that the object is created and destroyed in the same thread context, with the thread being a parameter to operators new and delete. (yes, I know, the operators could lookup the current thread, that isn't the point). Anyway, this being C++, I found other ways around my problem. I was just curious why the parallel to calling new with arguments doesn't exists for calling operator delete. I suspect this is one of those areas where the answer is "because it wasn't in the original standard and nobody has written a proposal to add it to the new standard." -josh -- [ See http://www.gotw.ca/resources/clcm.htm for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ]
From: Goran on 10 Feb 2010 08:13
On Feb 10, 2:16 am, Dino <dinoch...(a)gmail.com> wrote: > Why would you need to pass an argument to your delete call? Just to > invoke the correct delete function? I would think that at the time of > deletion the class should know how to properly clean itself up (even > if the delete was called because of an exception thrown in the > constructor). I would think not. If the ctor didn't finish, instance is not constructed, meaning that's in a state it just should not be in. But normally, e.g. destructor relies on class invariants that are established by ctor(s), so dtor can easily fail to work properly. Either that, either it has to take into account state variants that stem from unfinished ctors. That's complexity I'd like to avoid. (Not that this is a big problem in many-a-practical uses, but conceptually, I think it is not a foundation to build a language on). (Not related to Dino's post, but in general...) I think that Andy and Joshua are missing the purpose of the overloaded operator delete: it's __only__ purpose is to allow the compiler to know what cleanup function it should call IF overloaded operator new was called, BUT ctor blew up after that. Once operator new + ctor went through, the case is either 1. normal operator delete must know all there is to know WRT freeing memory __regardless___ of what overload of "operator new" was initially used or 2. dtor + specific memory-freeing function should be called. This is what Joshua and Andy would like to be replaced by a call to an overload of operator delete. But there are issues. Doing "delete (params) p;" is really not much simpler. Code-size-wise, it's two statements versus one - uh-oh, big deal. But most of the complexity stems from the necessity to know what operator new was called for a pointer we are about to "delete" - that one's the clincher, really. That realistically can't be done automatically, so programmer must work on it. Also e.g. smart pointers are out of question (that is, they need approach 1). All in all, what Joshua and Andy want would be additional feature with a __really__ small benefit. Goran. -- [ See http://www.gotw.ca/resources/clcm.htm for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ] |