[shared_ptr] delete shared_ptr

i'm excited to present you a technique which i occasionally invented shared pointers are very good helpers they help us to manage dynamically allocated memory however it seems so natural i have never seen so far that one be allowed to delete shared pointer like this: shared_ptr<int> p = new int, q = p; delete p; assert(!p); //neither assertion fires assert(q); in fact the technique is rather trivial provide a distinct class like this: template<typename type> struct deleter : shared_ptr_base<type> { void operator delete(void *p) { reinterpret_cast<ptr_base*>(p)->detach(); } }; and let the 'operator unspecified_type_convertible_to_bool()' return statically casted address of the ptr instance itself (or NULL) like this: template<typename type> inline shared_ptr<type>::operator const deleter<type>*() const { if (!data) return 0; const shared_ptr_base<type> *base = this; return static_cast<const safe_deleter<type>*>(base); //oops! a little hack... } minimum changes are needed to the existing library sources this way the example above works perfectly codepad.org is down so i just attached a toy programm with an implementation of this technique (works at least in msvc10) -- Pavel P.S. if you notice a grammar mistake or weird phrasing in my message please point it out

On 16 March 2011 15:44, Alexander Pshenichnikov <alpshenichnik@gmail.com>wrote:
codepad.org is down so i just attached a toy programm with an implementation of this technique (works at least in msvc10)
Please at least include required headers and add 'using' directives to the attached code, so that it will be enough to compile :)
What does this have to do with boost::shared_ptr? If you are requesting a feature where delete p does the same thing as p.reset(), that sounds like a very bad idea to me, because the expected semantics of the former (that the object is destroyed) is not what you get with the latter (the object is only destroyed when no one owns it). Not to mention error-prone as smart pointers should be discouraging people from ever explicitly delete-ing objects. -- Nevin ":-)" Liber <mailto:nevin@eviloverlord.com> (847) 691-1404

Nevin wrote on Thursday, March 17, 2011 at 4:44:15:
If you are requesting a feature where delete p does the same thing as p.reset(), that sounds like a very bad idea to me, because the expected semantics of the former (that the object is destroyed) is not what you get with the latter (the object is only destroyed when no one owns it). Not to mention error-prone as smart pointers should be discouraging people from ever explicitly delete-ing objects.
it can be applied to any smart pointer type shared_ptr is just the first that came to my (excited) mind i believe that more complete imitation of plain c pointers makes smart pointers better even in the case of smart_ptr possibility to use 'delete p;' construct is a good idea when you write a line like this delete p; your intention is that you no longer need the data pointed to by 'p' and it renders more consistent than p.reset(); or anything similar furthermore this can simplify template programming here is an example template<typename ptr_t> void takes_ownership(ptr_t p) { //do something with the data delete p; } takes_ownership(new data_t); //takes ownership shared_ptr<data_t> p = new data_t; takes_ownership(p); //or does it? and at last can you please give a couple of reasons why delete'ing smart pointers is a bad idea? -- Pavel P.S. if you notice a grammar mistake or weird phrasing in my message please point it out

-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 On Thursday, March 17, 2011, pavel wrote:
and at last can you please give a couple of reasons why delete'ing smart pointers is a bad idea?
It violates the fundamental premise of shared_ptr: shared ownership. Whoever deletes the object directly is taking total ownership of the object. -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.10 (GNU/Linux) iEYEARECAAYFAk2CUjsACgkQ5vihyNWuA4UZswCfWkCMXcVU/CdQ8/JKWtNerZFr 4eYAoMquMISHXZGgdgEdpxCfZ3Wf3wkn =LjH1 -----END PGP SIGNATURE-----

Frank wrote on Thursday, March 17, 2011 at 21:26:02:
It violates the fundamental premise of shared_ptr: shared ownership. Whoever deletes the object directly is taking total ownership of the object.
you misunderstood the point is that hypothetical_smart_ptr<int> p = new int, //allocating data q; p = q; //data intended to be shared now delete p; //equivalent to 'p.reset()' in the 'shared_ptr' case delete q; //<--actually releases allocated data it deletes or otherwise releases guarded resource only if no other smart pointer holds a reference to the resource -- Pavel P.S. if you notice a grammar mistake or weird phrasing in my message please point it out

On 17 March 2011 13:53, pavel <paul.cpprules@gmail.com> wrote:
it deletes or otherwise releases guarded resource only if no other smart pointer holds a reference to the resource
Yes, we know what reset does. You haven't given an argument as to why delete should do the same thing, and we've given you reasons why it isn't a good idea. -- Nevin ":-)" Liber <mailto:nevin@eviloverlord.com> (847) 691-1404

Nevin Liber wrote:
On 17 March 2011 13:53, pavel <paul.cpprules@gmail.com> wrote:
it deletes or otherwise releases guarded resource only if no other smart pointer holds a reference to the resource
Yes, we know what reset does. You haven't given an argument as to why delete should do the same thing, and we've given you reasons why it isn't a good idea.
+1 If you want to say that a specific smart pointer has no interest in the pointee anymore, I think the expression p = 0; covers those semantics better. I don't know whether the current Boost.Smart_Ptr implementation supports that syntax, but it might be a nice addition. (I.e., p = 0; means the same as p.reset();.) delete p; really suggests that the pointee is going to be destroyed, so if that's not what you intend you shouldn't use the syntax. -Julian

On 3/17/2011 2:13 PM, pavel wrote:
and at last can you please give a couple of reasons why delete'ing smart pointers is a bad idea?
Because it's a lie. "delete" should delete something, and not be overloaded to perform non-obvious, unrelated logic. A perfect example is how the proposed usage of "delete" confused Frank Mori Hess. Was it unreasonable for him to see "delete" and assume that it was actually deleting something? On 3/17/2011 2:13 PM, pavel wrote:
furthermore this can simplify template programming here is an example
template<typename ptr_t> void takes_ownership(ptr_t p) { //do something with the data delete p; }
The same can be accomplished using type traits or function overloading.

Kenny wrote on Thursday, March 17, 2011 at 22:08:51:
On 3/17/2011 2:13 PM, pavel wrote:
and at last can you please give a couple of reasons why delete'ing smart pointers is a bad idea?
Because it's a lie. "delete" should delete something, and not be overloaded to perform non-obvious, unrelated logic. A perfect example is how the proposed usage of "delete" confused Frank Mori Hess. Was it unreasonable for him to see "delete" and assume that it was actually deleting something? i disagree with you in my view it perfectly fits and i believe Frank just misread my message
The same can be accomplished using type traits or function overloading. sure it can
-- Pavel P.S. if you notice a grammar mistake or weird phrasing in my message please point it out

pavel wrote:
Kenny wrote on Thursday, March 17, 2011 at 22:08:51:
On 3/17/2011 2:13 PM, pavel wrote:
and at last can you please give a couple of reasons why delete'ing smart pointers is a bad idea?
Because it's a lie. "delete" should delete something, and not be overloaded to perform non-obvious, unrelated logic. A perfect example is how the proposed usage of "delete" confused Frank Mori Hess. Was it unreasonable for him to see "delete" and assume that it was actually deleting something?
i disagree with you in my view it perfectly fits and i believe Frank just misread my message
I completely agree with Kenny. The pointer isn't deleted. "delete" has very specific semantics and you are changing those to be something nebulous along this line: cannot be referenced any longer in this scope, whatever affect it may have on other code or the resource. _____ Rob Stewart robert.stewart@sig.com Software Engineer using std::disclaimer; Dev Tools & Components Susquehanna International Group, LLP http://www.sig.com IMPORTANT: The information contained in this email and/or its attachments is confidential. If you are not the intended recipient, please notify the sender immediately by reply and immediately delete this message and all its attachments. Any review, use, reproduction, disclosure or dissemination of this message or any attachment by an unintended recipient is strictly prohibited. Neither this message nor any attachment is intended as or should be construed as an offer, solicitation or recommendation to buy or sell any security or other financial instrument. Neither the sender, his or her employer nor any of their respective affiliates makes any warranties as to the completeness or accuracy of any of the information contained herein or that this message or any of its attachments is free of viruses.

-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 On Thursday, March 17, 2011, pavel wrote:
Kenny wrote on Thursday, March 17, 2011 at 22:08:51:
Because it's a lie. "delete" should delete something, and not be overloaded to perform non-obvious, unrelated logic. A perfect example is how the proposed usage of "delete" confused Frank Mori Hess. Was it unreasonable for him to see "delete" and assume that it was actually deleting something?
i disagree with you in my view it perfectly fits
Ok, I think I'm following what you want delete to do now. You're thinking that "delete GenericPointerObject" for should have the same effect on the pointed-to object as destroying the GenericPointerObject when GenericPointerObject is not a "plain old pointer". That would only be sort- of consistent with ordinary usage of delete if you viewed "plain old pointers" as a type that implies unique ownership. I don't see "plain old pointers" as implying anything about ownership. It's the "delete" part of "delete p" that implies the object should be destroyed, not the fact that p is a plain old pointer. -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.10 (GNU/Linux) iEYEARECAAYFAk2CZCkACgkQ5vihyNWuA4WqrACgzJ9sTpTvNEjJZLIKZDf3+Jrr yboAn2P9nCPz3Y9da8txZm1wnj3sQXXI =ONQR -----END PGP SIGNATURE-----

From: boost-bounces@lists.boost.org [mailto:boost-bounces@lists.boost.org] On Behalf Of Kenny Riddile Sent: Thursday, March 17, 2011 3:09 PM To: boost@lists.boost.org Subject: Re: [boost] [shared_ptr] delete shared_ptr On 3/17/2011 2:13 PM, pavel wrote:
and at last can you please give a couple of reasons why delete'ing smart pointers is a bad idea?
Because it's a lie. "delete" should delete something, and not be overloaded
I don't necessarily agree that it's a lie. I think it's simply stating an intention; the intention being that the current shared pointer is no longer interesting in the shared object; who cares if the shared object gets deleted under the covers. This is the mentality that one needs to have in a garbage-collected environment, since you get the same exact effect when you set a reference to null. Having said that; I don't yet feel Pavel has convinced me that changing the shared_pr library will buy anything significant. -Sid Sacek

On 3/18/2011 2:40 AM, Sid Sacek wrote:
I think it's simply stating an intention; the intention being that the current shared pointer is no longer interesting in the shared object; who cares if the shared object gets deleted under the covers. This is the mentality that one needs to have in a garbage-collected environment, since you get the same exact effect when you set a reference to null.
But it doesn't state that intention at all. The intention it very clearly states is that something *is* being deleted. The word "delete" has a very specific meaning in the English language. Assigning the shared_ptr to null or to another shared_ptr tracking a different object *does* state that intention, but "delete p;" and "p = 0;" are not, and should not, be the same.

On 3/18/2011 8:44 AM, Kenny Riddile wrote:
But it doesn't state that intention at all. The intention it very clearly states is that something *is* being deleted. The word "delete" has a very specific meaning in the English language. Assigning the shared_ptr to null or to another shared_ptr tracking a different object *does* state that intention, but "delete p;" and "p = 0;" are not, and should not, be the same.
I have to chime in and agree here. having "delete p" do *anything other* than p = 0 for a smart pointer would be suicidal. And *having* it just do p = 0 is asking for trouble. People will assume (since you can't tell from context) that it's *not* a smart pointer.

On 3/18/2011 11:00 AM, Eric J. Holtman wrote:
On 3/18/2011 8:44 AM, Kenny Riddile wrote:
But it doesn't state that intention at all. The intention it very clearly states is that something *is* being deleted. The word "delete" has a very specific meaning in the English language. Assigning the shared_ptr to null or to another shared_ptr tracking a different object *does* state that intention, but "delete p;" and "p = 0;" are not, and should not, be the same.
I have to chime in and agree here.
having "delete p" do *anything other* than p = 0 for a smart pointer would be suicidal.
That actually kind of sounds like the exact opposite of what I said :) What I said was that assigning any type of pointer to a new value signifies that you don't care about being able to access the previous value via that pointer. Calling delete on a pointer can only signify that you want to delete what that pointer points to. Since every call to shared_ptr::reset() doesn't result in a deletion, it is inappropriate to equate them. "reset" and "delete" do not mean the same thing in the context of a handle to a shared resource, like shared_ptr.

On 3/18/2011 11:11 AM, Kenny Riddile wrote:
having "delete p" do *anything other* than p = 0 for a smart pointer would be suicidal.
That actually kind of sounds like the exact opposite of what I said :)
Well, you elided my second point. My point was, clearly, that "delete p" can't really call delete. So, the only thing it can do is the equivalent of "p.reset". And I was arguing for just using "p.reset" (which I prefer over "p=0", because it's easier to search for)

On 3/18/2011 12:19 PM, Eric J. Holtman wrote:
On 3/18/2011 11:11 AM, Kenny Riddile wrote:
having "delete p" do *anything other* than p = 0 for a smart pointer would be suicidal.
That actually kind of sounds like the exact opposite of what I said :)
Well, you elided my second point. My point was, clearly, that "delete p" can't really call delete.
So, the only thing it can do is the equivalent of "p.reset".
And I was arguing for just using "p.reset" (which I prefer over "p=0", because it's easier to search for)
_______________________________________________ Unsubscribe& other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Agreed...sometimes typing is far inferior to speaking :)

On 18 March 2011 01:40, Sid Sacek <ssacek@securewatch24.com> wrote:
I think it's simply stating an intention; the intention being that the current shared pointer is no longer interesting in the shared object; who cares if the shared object gets deleted under the covers.
Suppose the shared object holds an open file descriptor or a lock on a mutex. It would be nice if the file actually got closed or the lock got released.
This is the mentality that one needs to have in a garbage-collected environment, since you get the same exact effect when you set a reference to null.
The single most important feature of C++ is that destruction of objects happen at well defined times. GC in C++ would separate destruction of objects from memory reclamation. Other GC languages have a harder time reclaiming resources other than memory because they don't or can't separate out these two distinct phases. -- Nevin ":-)" Liber <mailto:nevin@eviloverlord.com> (847) 691-1404

Sid wrote on Friday, March 18, 2011 at 9:40:52:
I don't necessarily agree that it's a lie.
I think it's simply stating an intention; the intention being that the current shared pointer is no longer interesting in the shared object; who cares if the shared object gets deleted under the covers. This is the mentality that one needs to have in a garbage-collected environment, since you get the same exact effect when you set a reference to null.
Having said that; I don't yet feel Pavel has convinced me that changing the shared_pr library will buy anything significant.
you got exactly my point! since for example 'smart_ptr' claims to be a pointer AND it allows such horrible thing like p = 0; //'p.reset()' is implied?? why shouldn't it be 'delete'ed? the 'delete' operation does much less harm than that null assignment otherwise it should be named like 'shared_guard' or something and the semantics of deletion is well defined in the case of smart pointer, which states "i don't want the data pointed to anymore" (excuse me for repetition) eventually the user has done the duty 'delete'ing the data and generally doesn't care if the data gets deleted immediately or when all other references quit sorry for not replying every message, i hope this answers all those questions -- Pavel P.S. if you notice a grammar mistake or weird phrasing in my message please point it out

AMDG On 03/18/2011 10:08 AM, pavel wrote:
Sid wrote on Friday, March 18, 2011 at 9:40:52:
I think it's simply stating an intention; the intention being that the current shared pointer is no longer interesting in the shared object; who cares if the shared object gets deleted under the covers. This is the mentality that one needs to have in a garbage-collected environment, since you get the same exact effect when you set a reference to null. Having said that; I don't yet feel Pavel has convinced me that changing the shared_pr library will buy anything significant. you got exactly my point!
since for example 'smart_ptr' claims to be a pointer AND it allows such horrible thing like
p = 0; //'p.reset()' is implied??
First of all, shared_ptr doesn't allow this. Second, how is it horrible? Of course it is (almost) like p.reset(). Assigning anything to a shared_ptr decrements the reference count on the old value.
why shouldn't it be 'delete'ed?
Because the behaviour of delete is well-known. You want add a new meaning which is similar enough to cause confusion. I object to using clever tricks like this just because we can. In my opinion, the only legitimate reason to "overload" delete like this would be to allow a template to treat raw pointers and shared_ptrs polymorphically. Such code is probably wrong anyway.
the 'delete' operation does much less harm than that null assignment
That depends. a) Using delete when you should use null assignment: probable memory corruption. b) Using null assignment when you should use delete: resource leak. Which is worse?
otherwise it should be named like 'shared_guard' or something
Huh?
and the semantics of deletion is well defined in the case of smart pointer,
Except that the tricks you use to implement it result in undefined behavior...
which states "i don't want the data pointed to anymore" (excuse me for repetition)
See, I think this is the basic problem. Who is "I" here? Is it the local code or the entire program? For the smart pointer case, you're saying "the current function no longer needs the object." For the raw pointer case, you're saying "nothing in this program needs the object any more." These are fundamentally different, therefore IMHO, spelling them the same way is only going to cause problems.
eventually the user has done the duty 'delete'ing the data and generally doesn't care if the data gets deleted immediately or when all other references quit
sorry for not replying every message, i hope this answers all those questions
In Christ, Steven Watanabe

Steven wrote on Friday, March 18, 2011 at 21:02:13:
First of all, shared_ptr doesn't allow this.
agree, my bad
Second, how is it horrible? Of course it is (almost) like p.reset(). Assigning anything to a shared_ptr decrements the reference count on the old value.
rephrasing your words: how is 'delete p' a bad idea? it's obvious it is almost like 'p.reset()' deleting a smart pointer decrements the reference counter and releases the memory if the count drops to zero
Because the behaviour of delete is well-known. You want add a new meaning which is similar enough to cause confusion. I object to using clever tricks like this just because we can. In my opinion, the only legitimate reason to "overload" delete like this would be to allow a template to treat raw pointers and shared_ptrs polymorphically. Such code is probably wrong anyway.
that's what we try to figure out here and no, it's the other way around: the unfairness that smart pointers can not be deleted like plain pointers led to the development of the fancy stuff
That depends.
a) Using delete when you should use null assignment: probable memory corruption. b) Using null assignment when you should use delete: resource leak.
Which is worse?
both the intention when deleting a smart pointer is to gently release the reference to the data it currently points to -- no memory corruption or leak intended
Except that the tricks you use to implement it result in undefined behavior...
i inspected the std and didn't find anything which may result in undefined behavior did i miss anything?
See, I think this is the basic problem. Who is "I" here? Is it the local code or the entire program? For the smart pointer case, you're saying "the current function no longer needs the object." For the raw pointer case, you're saying "nothing in this program needs the object any more." These are fundamentally different, therefore IMHO, spelling them the same way is only going to cause problems.
i'll rephrase it: deleting a pointer states that the scope of the pointer instance does not need the data pointed to (by the pointer instance) here a pointer may be a plain pointer or a smart one; the scope of the pointer may be a function or whole program no offence but is my english really so bad that almost noone can understand what i am talking about? -- Pavel P.S. if you notice a grammar mistake or weird phrasing in my message please point it out

On 3/18/2011 4:54 PM, pavel wrote:
i'll rephrase it: deleting a pointer states that the scope of the pointer instance does not need the data pointed to (by the pointer instance)
No, deleting a pointer asserts that *nobody* needs the data that the pointer points to. It is conceptually confusing to allow someone to "delete" something and yet have that something still exist.

On Fri, Mar 18, 2011 at 1:54 PM, pavel <paul.cpprules@gmail.com> wrote: [...]
no offence but is my english really so bad that almost noone can understand what i am talking about?
I don't think so. If you're adamant about doing this, why don't you just use a delete_ (or, maybe better spelled, release or reset or delete_or_reset) free function that's overloaded both for raw pointers and for smart pointers? I'm not convinced you have a legitimate use case to begin with, but under the assumption that you do, this seems like a better resolution than playing games with the smart_ptr interface... - Jeff

Jeffrey wrote on Saturday, March 19, 2011 at 0:25:08:
no offence but is my english really so bad that almost noone can understand what i am talking about? I don't think so.
thanks for that
If you're adamant about doing this, why don't you just use a delete_ (or, maybe better spelled, release or reset or delete_or_reset) free function that's overloaded both for raw pointers and for smart pointers? I'm not convinced you have a legitimate use case to begin with, but under the assumption that you do, this seems like a better resolution than playing games with the smart_ptr interface...
because if we had an alternative of 'delete_(p)' or the like and 'p.reset()' the latter is definitely preferable but 'delete p' form imho is more natural than both of the above eventually peter dimov gave a strong reason regarding smart_ptr: Peter wrote on Saturday, March 19, 2011 at 0:41:23:
There is a specific compile-fail test in shared_ptr for 'delete p'. The reason that you typically need this to be a compile-time error is that when transitioning a large code base from raw pointers to shared_ptr you usually want the compiler to point these out to you so that you can decide what to do with them.
which i agree with in this particular case but not in the general case regarding smart pointers though it is merely a technical aspect of porting sources ideally when you set the pointer type to be a smart pointer in an existing source code (which worked correctly) nothing should change -- Pavel P.S. if you notice a grammar mistake or weird phrasing in my message please point it out

pavel wrote:
rephrasing your words: how is 'delete p' a bad idea? it's obvious it is almost like 'p.reset()'
There is a specific compile-fail test in shared_ptr for 'delete p'. The reason that you typically need this to be a compile-time error is that when transitioning a large code base from raw pointers to shared_ptr you usually want the compiler to point these out to you so that you can decide what to do with them.

AMDG On 03/18/2011 01:54 PM, pavel wrote:
Steven wrote on Friday, March 18, 2011 at 21:02:13:
Second, how is it horrible? Of course it is (almost) like p.reset(). Assigning anything to a shared_ptr decrements the reference count on the old value. rephrasing your words: how is 'delete p' a bad idea? it's obvious it is almost like 'p.reset()'
No it isn't. The difference is that assignment is a basic operation for a smart_ptr, and it's behaving in the normal way. It isn't a matter of being "almost like" reset.
Except that the tricks you use to implement it result in undefined behavior... i inspected the std and didn't find anything which may result in undefined behavior
did i miss anything?
[expr.delete] "...In the first alternative (delete object), the value of the operand of delete may be a null pointer value, a pointer to a non-array object created by a previous new-expression, or a pointer to a subobject (1.8) representing a base class of such an object (Clause 10). If not, the behavior is undefined." In Christ, Steven Watanabe

Steven wrote on Saturday, March 19, 2011 at 1:31:51:
rephrasing your words: how is 'delete p' a bad idea? it's obvious it is almost like 'p.reset()'
No it isn't. The difference is that assignment is a basic operation for a smart_ptr, and it's behaving in the normal way. It isn't a matter of being "almost like" reset.
i see your point but you don't want to see mine
[expr.delete]
"...In the first alternative (delete object), the value of the operand of delete may be a null pointer value, a pointer to a non-array object created by a previous new-expression, or a pointer to a subobject (1.8) representing a base class of such an object (Clause 10). If not, the behavior is undefined."
it looks like you are citing the old std (or i have a corrupted copy) here is the full citation of 5.3.5.2 of ISO/IEC 14882:2003(E) which, i guess, you are referring to: "If the operand has a class type, the operand is converted to a pointer type by calling the above-mentioned conversion function, and the converted operand is used in place of the original operand for the remainder of this section. In either alternative, if the value of the operand of delete is the null pointer the operation has no effect. In the first alternative (delete object), the value of the operand of delete shall be a pointer to a non-array object or a pointer to a sub-object (1.8) representing a base class of such an object (clause 10). If not, the behavior is undefined. In the second alternative (delete array), the value of the operand of delete shall be the pointer value which resulted from a previous array new-expression.72) If not, the behavior is undefined. [Note: this means that the syntax of the delete-expression must match the type of the object allocated by new, not the syntax of the new-expression. ] [Note: a pointer to a const type can be the operand of a delete-expression; it is not necessary to cast away the constness (5.2.11) of the pointer expression before it is used as the operand of the delete-expression.]" feel free to prove me wrong -- Pavel P.S. if you notice a grammar mistake or weird phrasing in my message please point it out

AMDG On 03/19/2011 03:16 AM, pavel wrote:
Steven wrote on Saturday, March 19, 2011 at 1:31:51:
"...In the first alternative (delete object), the value of the operand of delete may be a null pointer value, a pointer to a non-array object created by a previous new-expression, or a pointer to a subobject (1.8) representing a base class of such an object (Clause 10). If not, the behavior is undefined." it looks like you are citing the old std (or i have a corrupted copy)
Actually, I got it from n3242 which is a recent C++0x draft.
here is the full citation of 5.3.5.2 of ISO/IEC 14882:2003(E) which, i guess, you are referring to:
"<snip>"
feel free to prove me wrong
Okay. Let's do this a different way (a little later in the section): "In the first alternative (delete object), if the static type of the operand is different from its dynamic type, the static type shall be a base class of the operand’s dynamic type and the static type shall have a virtual destructor or the behavior is undefined." In Christ, Steven Watanabe

Steven wrote on Saturday, March 19, 2011 at 18:40:26:
Actually, I got it from n3242 which is a recent C++0x draft.
are you sure that this draft is going to become the final version of std? if so further discussion is pointless since the std kills the very opportunity to implement such a feature (and some custom allocation strategies as well)
Okay. Let's do this a different way (a little later in the section):
"In the first alternative (delete object), if the static type of the operand is different from its dynamic type, the static type shall be a base class of the operand’s dynamic type and the static type shall have a virtual destructor or the behavior is undefined."
i believe this part concerns slicing as when one deletes an object of some derived class D using pointer to the base class B this way ~D() destructor has no chance to be executed and we have the whole bunch of unwanted effects furthermore when '::delete operator()' function is called the compiler may miscalculate the size of the object to be deleted since sizeof(D) may differ from sizeof(B) and the deallocation function likely be supplied with wrong size argument which again may cause unexpected effects in my variant of implementation all destructors involved are trivial (read: they are never called) and the global deallocation function ('::operator delete()') is never called on the operand of the delete expression so i believe it shouldn't cause undefined behavior anyway -- Pavel P.S. if you notice a grammar mistake or weird phrasing in my message please point it out

AMDG On 03/20/2011 02:30 AM, pavel wrote:
Steven wrote on Saturday, March 19, 2011 at 18:40:26:
Actually, I got it from n3242 which is a recent C++0x draft. are you sure that this draft is going to become the final version of std?
Nope. It definitely will get some more updates. However, I think it highly unlikely that this restriction will be removed. It already existed for array delete, and this makes the two more consistent.
"In the first alternative (delete object), if the static type of the operand is different from its dynamic type, the static type shall be a base class of the operand’s dynamic type and the static type shall have a virtual destructor or the behavior is undefined." i believe this part concerns slicing as when one deletes an object of some derived class D using pointer to the base class B
this way ~D() destructor has no chance to be executed and we have the whole bunch of unwanted effects
furthermore when '::delete operator()' function is called the compiler may miscalculate the size of the object to be deleted since sizeof(D) may differ from sizeof(B) and the deallocation function likely be supplied with wrong size argument which again may cause unexpected effects
in my variant of implementation all destructors involved are trivial (read: they are never called)
Not guaranteed.
and the global deallocation function ('::operator delete()') is never called on the operand of the delete expression
Irrelevant.
so i believe it shouldn't cause undefined behavior anyway
Undefined behaviour does not mean that the code will do bad things. It means that the standard does not specify what happens. Don't try to second guess the implementation like this. Just because you can't think of anything that can go wrong, does not mean that it's safe. In Christ, Steven Watanabe

steven, you convinced me that this trick is too dirty to be used in general case so i'm going to drop this topic thank you and robert and everyone else for contributing to this thread -- Pavel P.S. if you notice a grammar mistake or weird phrasing in my message please point it out

pavel wrote:
Steven wrote on Saturday, March 19, 2011 at 1:31:51:
rephrasing your words: how is 'delete p' a bad idea? it's obvious it is almost like 'p.reset()'
No it isn't. The difference is that assignment is a basic operation for a smart_ptr, and it's behaving in the normal way. It isn't a matter of being "almost like" reset.
i see your point but you don't want to see mine
There's a difference between seeing another's point and agreeing with it. Steven understands your proposal just fine from what I've read in the discussion.
here is the full citation of 5.3.5.2 of ISO/IEC 14882:2003(E) which, i guess, you are referring to:
"If the operand has a class type, the operand is converted to a pointer type by calling the above-mentioned conversion function, and the converted operand is used in place of the original operand for the remainder of this section. In either alternative, if the value of the operand of delete is the null pointer the operation has no effect. In the first alternative (delete object), the value of the operand of delete shall be a pointer to a non-array object or a pointer to a sub-object (1.8) representing a base class of such an object (clause 10). If not, the behavior is undefined."
IOW, a shared_ptr sp must provide an implicit conversion to T * in order for delete sp to work, because delete only operates on T *'s, which then introduces an unwanted implicit conversion in shared_ptr. _____ Rob Stewart robert.stewart@sig.com Software Engineer using std::disclaimer; Dev Tools & Components Susquehanna International Group, LLP http://www.sig.com IMPORTANT: The information contained in this email and/or its attachments is confidential. If you are not the intended recipient, please notify the sender immediately by reply and immediately delete this message and all its attachments. Any review, use, reproduction, disclosure or dissemination of this message or any attachment by an unintended recipient is strictly prohibited. Neither this message nor any attachment is intended as or should be construed as an offer, solicitation or recommendation to buy or sell any security or other financial instrument. Neither the sender, his or her employer nor any of their respective affiliates makes any warranties as to the completeness or accuracy of any of the information contained herein or that this message or any of its attachments is free of viruses.

pavel wrote:
Steven wrote on Friday, March 18, 2011 at 21:02:13:
Second, how is it horrible? Of course it is (almost) like p.reset(). Assigning anything to a shared_ptr decrements the reference count on the old value.
rephrasing your words: how is 'delete p' a bad idea? it's obvious it is almost like 'p.reset()'
As has been repeated often, because the two mean quite different things and no one else, it would seem, is at all comfortable with your conflating the two.
deleting a smart pointer decrements the reference counter and releases the memory if the count drops to zero
We understand, quite well, what you are proposing.
Because the behaviour of delete is well-known. You want add a new meaning which is similar enough to cause confusion. I object to using clever tricks like this just because we can. In my opinion, the only legitimate reason to "overload" delete like this would be to allow a template to treat raw pointers and shared_ptrs polymorphically. Such code is probably wrong anyway.
that's what we try to figure out here
No, that's what you proposed and are now trying to force on others.
i'll rephrase it: deleting a pointer states that the scope of the pointer instance does not need the data pointed to (by the pointer instance)
here a pointer may be a plain pointer or a smart one; the scope of the pointer may be a function or whole program
Understood...from the start.
no offence but is my english really so bad that almost noone can understand what i am talking about?
Nope. Your English has been just fine. We understand, and have done so from the start, what you've proposed and continue to dislike the idea for technical, semantic, and aesthetic reasons. _____ Rob Stewart robert.stewart@sig.com Software Engineer using std::disclaimer; Dev Tools & Components Susquehanna International Group, LLP http://www.sig.com IMPORTANT: The information contained in this email and/or its attachments is confidential. If you are not the intended recipient, please notify the sender immediately by reply and immediately delete this message and all its attachments. Any review, use, reproduction, disclosure or dissemination of this message or any attachment by an unintended recipient is strictly prohibited. Neither this message nor any attachment is intended as or should be construed as an offer, solicitation or recommendation to buy or sell any security or other financial instrument. Neither the sender, his or her employer nor any of their respective affiliates makes any warranties as to the completeness or accuracy of any of the information contained herein or that this message or any of its attachments is free of viruses.

Please at least include required headers and add 'using' directives to the attached code, so that it will be enough to compile :)
on Wednesday, March 16, 2011 at 22:44:17 Alexander wrote: the attached file in the original message works with msvc10 tell me if it doesn't on Wednesday, March 16, 2011 at 23:09:29 Kenny wrote:
Maybe I'm missing something but how is "delete p;" different from "p.reset();" ? in this particular case they are not (i.e. they are the same)
Am I missing something? with current implementation of boost::shared_ptr it doesn't work
on Wednesday, March 16, 2011 at 23:23:04 Robert wrote: that's the whole point -- Pavel P.S. if you notice a grammar mistake or weird phrasing in my message please point it out

On 3/16/2011 3:23 PM, pavel novikov wrote:
i'm excited to present you a technique which i occasionally invented shared pointers are very good helpers they help us to manage dynamically allocated memory however it seems so natural i have never seen so far that one be allowed to delete shared pointer like this:
shared_ptr<int> p = new int, q = p; delete p; assert(!p); //neither assertion fires assert(q);
in fact the technique is rather trivial provide a distinct class like this:
template<typename type> struct deleter : shared_ptr_base<type> { void operator delete(void *p) { reinterpret_cast<ptr_base*>(p)->detach(); } };
and let the 'operator unspecified_type_convertible_to_bool()' return statically casted address of the ptr instance itself (or NULL) like this:
template<typename type> inline shared_ptr<type>::operator const deleter<type>*() const { if (!data) return 0; const shared_ptr_base<type> *base = this; return static_cast<const safe_deleter<type>*>(base); //oops! a little hack... }
minimum changes are needed to the existing library sources this way the example above works perfectly
codepad.org is down so i just attached a toy programm with an implementation of this technique (works at least in msvc10)
_______________________________________________ Unsubscribe& other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Maybe I'm missing something but how is "delete p;" different from "p.reset();" ?

On Wed, Mar 16, 2011 at 7:23 PM, pavel novikov <paul.cpprules@gmail.com>wrote:
i'm excited to present you a technique which i occasionally invented shared pointers are very good helpers they help us to manage dynamically allocated memory however it seems so natural i have never seen so far that one be allowed to delete shared pointer like this:
shared_ptr<int> p = new int, q = p; delete p; assert(!p); //neither assertion fires assert(q);
Am I missing something?
cat shared.cpp #include <boost/shared_ptr.hpp>
int main( ) { boost::shared_ptr<int> p = new int, q = p; delete p; assert(!p); //neither assertion fires assert(q); }
g++ -I ~/Downloads/boost_1_45_0 -o shared shared.cpp shared.cpp: In function ‘int main()’: shared.cpp:5:40: error: conversion from ‘int*’ to non-scalar type ‘boost::shared_ptr<int>’ requested shared.cpp:6:12: error: type ‘class boost::shared_ptr<int>’ argument given to ‘delete’, expected pointer
- Rob.

On Wed, Mar 16, 2011 at 8:23 PM, pavel novikov <paul.cpprules@gmail.com> wrote:
i'm excited to present you a technique which i occasionally invented shared pointers are very good helpers
yes they are. While this topic is hot, I'd like to add a use-case for shared_ptr that is probably not too obvious: Assume the following class interface: // A class that works with points. In order to do so, it requires an accelerator data structure to speed up computations. // Building an accelerator is costly and should be avoided if such an accelerator over the points has already been built. class works_with_points { // Construct from points. Need to generate accelerator. works_with_points (const array_of_points &points) : _acc(new accelarator_over_points(points)) {} // Construct from pre-existing accelerator. // Accelerator is guaranteed to live as long as this class instance does. works_with_points (boost::shared_ptr<accelarator_over_points const> accel) : _acc(accel) {} // Construct from pre-existing accelerator. works_with_points (const accelarator_over_points &accel) : _acc(&accel, null_deleter()) {} private: boost::shared_ptr<accelarator_over_points const> _acc; }; Best regards, Christoph

On Thu, Mar 17, 2011 at 10:44 AM, Christoph Heindl <christoph.heindl@gmail.com> wrote:
// Construct from pre-existing accelerator. // Accelerator is guaranteed to live as long as this class instance does. works_with_points (boost::shared_ptr<accelarator_over_points const> accel) : _acc(accel) {}
// Construct from pre-existing accelerator. works_with_points (const accelarator_over_points &accel) : _acc(&accel, null_deleter()) {}
Typo in documentation and code. Should read // Construct from pre-existing accelerator. works_with_points (boost::shared_ptr<accelerator_over_points const> accel) : _acc(accel) {} // Construct from pre-existing accelerator. // Accelerator is guaranteed to live as long as this class instance does. works_with_points (const accelerator_over_points &accel) : _acc(&accel, null_deleter()) {} You get the point :) Best regards, Christoph

On Thu, Mar 17, 2011 at 10:56 AM, Joshua Juran <jjuran@gmail.com> wrote:
Is there a reason to pass the shared_ptr by value instead of const reference?
I'm not sure. After reading several discussions on the web [1,2] I concluded that I'll stick with by-value. [1] http://stackoverflow.com/questions/327573/c-passing-references-to-boostshare... [2] http://stackoverflow.com/questions/3310737/shared-ptr-by-reference-or-by-val... At a certain point of time in the past this was included in boost.shared_ptr documentation. I quickly skimmed over the docs but couldn't find any reference. Best regards, Christoph

On Mar 17, 2011, at 3:24 AM, Christoph Heindl wrote:
On Thu, Mar 17, 2011 at 10:56 AM, Joshua Juran <jjuran@gmail.com> wrote:
Is there a reason to pass the shared_ptr by value instead of const reference?
I'm not sure. After reading several discussions on the web [1,2] I concluded that I'll stick with by-value.
[1] http://stackoverflow.com/questions/327573/c-passing-references-to-boostshare... [2] http://stackoverflow.com/questions/3310737/shared-ptr-by-reference-or-by-val...
My understanding is that the arguments for pass-by-value boil down to: (1) The called function might cause some side effect which includes destroying the referenced object before using the object. This doesn't apply in your case, since you're just constructing a copy. (2) Another thread might destroy the object before the called function uses it. This is a red herring: Either the calling function has its own local copy, which will persist until the called function returns, or it's using storage accessible to another thread, in which case it's vulnerable -- but passing the shared_ptr by value to the called function doesn't close that vulnerability. The same hypothetical thread could either release the shared resource (reset()) or destroy the storage for the shared_ptr itself before the function call occurs. If this is in fact a risk (which it may well not be) then the calling code needs to arrange serialized access and either store its own local copy of the shared_ptr before passing it to another function or maintain a lock for the duration of the function call. One of the C++ best practices (from the book of the same name) is avoiding premature pessimization. Josh

On Thu, Mar 17, 2011 at 1:14 PM, Joshua Juran <jjuran@gmail.com> wrote:
One of the C++ best practices (from the book of the same name) is avoiding premature pessimization.
Definitely true. However, that wasn't the point of my post (it's rather the constructor that takes accelarator_over_points per reference). Secondy, it's not pessimization in my case, rather following existing guidelines (boost.shared_ptr docs) and avoiding to think about possible side-effects some code might cause :) Best regards.
participants (16)
-
Alexander Pshenichnikov
-
Christoph Heindl
-
Eric J. Holtman
-
Frank Mori Hess
-
Jeffrey Lee Hellrung, Jr.
-
Joshua Juran
-
Julian Gonggrijp
-
Kenny Riddile
-
Nevin Liber
-
pavel
-
pavel novikov
-
Peter Dimov
-
Robert Jones
-
Sid Sacek
-
Steven Watanabe
-
Stewart, Robert