Rationale for explicit ctors in boost smart pointers
Hi, I was wondering why e.g. boost:shared_ptr has an explicit constructor. This makes automatic conversion from T* to shared_ptr<T> impossible. The lack of the opposite conversion is covered by the FAQ and reasonable; however, I couldn't think of a good reason why I shouldn't be able to do something like this: std::set< boost::shared_ptr<Foo> > coll; coll.insert(new Foo); // error: No implicit conversion from Foo* to shared_ptr<Foo> Best regards, Matthias
Matthias Kaeppler wrote:
Hi,
I was wondering why e.g. boost:shared_ptr has an explicit constructor. This makes automatic conversion from T* to shared_ptr<T> impossible.
Correct, the intent of the explicit constructor is to disable implicit conversions from T*.
The lack of the opposite conversion is covered by the FAQ and reasonable; however, I couldn't think of a good reason why I shouldn't be able to do something like this:
std::set< boost::shared_ptr<Foo> > coll; coll.insert(new Foo);
One reason is that the pointer constructor assumes ownership of the pointer and as such, it imposes the requirement that the pointer has to be delete-able. The design of shared_ptr is based on the premise that the user assumes the responsibility of constructing the shared_ptr with a valid pointer (and not invalidating the pointer afterwards). In return, shared_ptr promises that the rest of the operations are safe and the passed pointer will be deleted exactly once, using its original type. Therefore, when doing a code review, you have to concentrate on shared_ptr constructors (and the reset alias). For this to be possible, you have to be able to locate them easily. If shared_ptr had an implicit constructor, all kinds of innocent statements of the form coll.insert( p ); could potentially create a shared_ptr, making the review much harder. For another reason, see the Best Practices section of the documentation.
Peter Dimov wrote:
One reason is that the pointer constructor assumes ownership of the pointer and as such, it imposes the requirement that the pointer has to be delete-able. Not sure what you're getting at here. Do you mean, you want to avoid statements like:
coll.insert(NULL); // coll is a collection of smart pointers ?
The design of shared_ptr is based on the premise that the user assumes the responsibility of constructing the shared_ptr with a valid pointer (and not invalidating the pointer afterwards). In return, shared_ptr promises that the rest of the operations are safe and the passed pointer will be deleted exactly once, using its original type. Well, yes, that's why one uses a smart pointer in the first place. To completely move responsibility for allocating and freeing memory to the smart pointer device.
Therefore, when doing a code review, you have to concentrate on shared_ptr constructors (and the reset alias). For this to be possible, you have to be able to locate them easily. If shared_ptr had an implicit constructor, all kinds of innocent statements of the form
coll.insert( p );
could potentially create a shared_ptr, making the review much harder.
Sorry, you have lost me here. The reason I would want to use some form of smart pointer facility is to pass the burden of memory management to some other instance. IOW, I don't want to care anymore. Why would I want to concentrate on shared_ptr ctors on a code review? I assume that it's handled correctly as long as I don't interfere (what you said before).
For another reason, see the Best Practices section of the documentation. I'll do that :)
Regards, Matthias
Matthias Kaeppler wrote:
Peter Dimov wrote:
One reason is that the pointer constructor assumes ownership of the pointer and as such, it imposes the requirement that the pointer has to be delete-able. Not sure what you're getting at here. Do you mean, you want to avoid statements like:
coll.insert(NULL); // coll is a collection of smart pointers ?
No, it's statements like coll.insert( &x ); coll.insert( this ); coll.insert( p ); // where p doesn't come from new that need to be avoided as they would lead to undefined behavior.
Peter Dimov wrote:
No, it's statements like
coll.insert( &x ); coll.insert( this ); coll.insert( p ); // where p doesn't come from new
that need to be avoided as they would lead to undefined behavior. Yes, that makes sense indeed. Thanks Peter.
- Matthias
participants (2)
-
Matthias Kaeppler
-
Peter Dimov