Hi, i'm wondering if there is a nice smart pointer in boost to implement PImpl. I found an implementation here: [1]. So, does boost provide a smart pointer which does play nice with pimpl, so that one doesn't need to provide a destructor, copyconstructor and assignment operator for the default cases? --David [1] http://www.octopull.demon.co.uk/arglib/TheGrin.html.
shared_ptr is just what you want David Gruener 写道:
Hi, i'm wondering if there is a nice smart pointer in boost to implement PImpl. I found an implementation here: [1]. So, does boost provide a smart pointer which does play nice with pimpl, so that one doesn't need to provide a destructor, copyconstructor and assignment operator for the default cases?
--David
[1] http://www.octopull.demon.co.uk/arglib/TheGrin.html. _______________________________________________ Boost-users mailing list Boost-users@lists.boost.org http://lists.boost.org/mailman/listinfo.cgi/boost-users
On 4/27/05, David Gruener
i'm wondering if there is a nice smart pointer in boost
Did you even bother to check? http://boost.org/libs/smart_ptr/smart_ptr.htm http://boost.org/libs/smart_ptr/sp_techniques.html#pimpl -- Caleb Epstein caleb dot epstein at gmail dot com
have you looked at shared_ptr? i believe the docs even mention using
it for pimpl.
On 4/27/05, David Gruener
Hi, i'm wondering if there is a nice smart pointer in boost to implement PImpl. I found an implementation here: [1]. So, does boost provide a smart pointer which does play nice with pimpl, so that one doesn't need to provide a destructor, copyconstructor and assignment operator for the default cases?
--David
[1] http://www.octopull.demon.co.uk/arglib/TheGrin.html. _______________________________________________ Boost-users mailing list Boost-users@lists.boost.org http://lists.boost.org/mailman/listinfo.cgi/boost-users
-- Cory Nelson http://www.int64.org
Hello, thanks for your answers. Yes, of course, i looked at the boost smart pointers. But, well, isn't a shared_ptr a shared_ptr because it shares ownership (via ref. counting)? :] What i expect is, that pimpl defaults to *deep*copying of the hidden members, when copying the object. (As it would happen, if there is no PImpl object on default copy construction). I don't get it, why shared_ptr is suggested without any hint (do i overlooked that?) that the private members are now shared (that basicly means "are the same") across the objects, which isn't the *primary* goal of PImpl, IMHO. The primary goal of PImpl is to hide private members and therefore act as a compilation firewall. Sharing private data is nice in cases but should *not* be the default behaviour. I think that still leaves my question if boost has a template for member hiding, with the (IMHO nice) results as documented in the url i gave. And, if not, whouln't it make sense to have such one? Best Regards, David
David Gruener wrote:
Hello,
thanks for your answers. Yes, of course, i looked at the boost smart pointers. But, well, isn't a shared_ptr a shared_ptr because it shares ownership (via ref. counting)? :]
Only if you pass it to another object. It it is a private shared_ptr then it gets automatically deleted, but won't get shared around. But what about scoped_ptr? Cheers Russell
Russell Hind wrote:
Only if you pass it to another object. It it is a private shared_ptr then it gets automatically deleted, but won't get shared around.
What i mean is, that if a class is implemented with a pimpl structure using boost::shared_ptr this A a; A b(a); would result in that changing private members of a changes private members of b, which one doesn't want in the default cases of pimpl.
But what about scoped_ptr?
No, scoped_ptr is noncopyable. Whats needed is a template with deepcopying the parameter struct (or cloning) and no need of an complete type at the point of the declaration of the pimpl. --David
David Gruener wrote:
Russell Hind wrote:
Only if you pass it to another object. It it is a private shared_ptr then it gets automatically deleted, but won't get shared around.
What i mean is, that if a class is implemented with a pimpl structure using boost::shared_ptr this
A a; A b(a);
would result in that changing private members of a changes private members of b, which one doesn't want in the default cases of pimpl.
and if you define: class A { class Impl; typedef boost::shared_ptr<Impl> tPimpl; tPimpl mPimpl; ... }; A::A( const A::A& a ):mPimpl( new Impl( *a.mPimpl ) ){} and don't forget operator=; You get the deep copy semantics that your looking for don't you?
But what about scoped_ptr?
No, scoped_ptr is noncopyable. Whats needed is a template with deepcopying the parameter struct (or cloning) and no need of an complete type at the point of the declaration of the pimpl.
I'd think scoped_ptr works above as well. Jeff Flinn
Jeff Flinn wrote:
A::A( const A::A& a ):mPimpl( new Impl( *a.mPimpl ) ){} and don't forget operator=; You get the deep copy semantics that your looking for don't you?
Then, whats the benefit here over using a plain pointer or std::auto_ptr? The goal of using a smart pointer with deep copy semantics is that you *dont* have to write those stuff by yourself.
I'd think scoped_ptr works above as well.
Again, scoped_ptr is noncopyable, and see above. :] --David
David Gruener wrote:
Jeff Flinn wrote:
A::A( const A::A& a ):mPimpl( new Impl( *a.mPimpl ) ){} and don't forget operator=; You get the deep copy semantics that your looking for don't you?
Then, whats the benefit here over using a plain pointer or std::auto_ptr? The goal of using a smart pointer with deep copy semantics is that you *dont* have to write those stuff by yourself.
Well, you don't have to worry about the destructor with shared_ptr or scoped_ptr. It's your call as to which to use so that you get the appropriate semantics.
I'd think scoped_ptr works above as well.
Again, scoped_ptr is noncopyable, and see above. :]
You're not copying the pointer, you're copying the pointee with deep copy semantics. Jeff Flinn Applied Dynamics, International
David Gruener wrote:
I think that still leaves my question if boost has a template for member hiding, with the (IMHO nice) results as documented in the url i gave.
No, Boost doesn't have a deep copy smart pointer. I wrote such a pointer several years ago: http://lists.boost.org/MailArchives/boost/msg21930.php http://groups.yahoo.com/group/boost/message/15313 http://groups.yahoo.com/group/boost/files/impl_ptr/impl_ptr.html but I never proposed it for Boost. The reason that I didn't propose it is that I don't use it. :-)
"David Gruener"
Peter Dimov wrote:
but I never proposed it for Boost. The reason that I didn't propose it is that I don't use it. :-)
I would use it! :] Well, am i the only one who needs this? :(
--David
policy_ptr is up for review and it should cover deep copy semantic. Gennadiy
The boost::scopted_ptr is the best way to implement this. No need for
shared_ptr because pimpl is usually not shared (until you implement
some kind of lazy copy-on-write, where shared_ptr _is_ very useful).
It can be also implemented with std::auto_ptr but it more dangerous,
because it will pass the compilation if you forget to implement copy
constructor and operator=(). In that case, the results will be
disastrous - I guess anyone remembers what auto_ptr's copy operator
does...
And another pitfal with both auto_ptr and shared_ptr (at least on
VC7.1 compiler) is if you don't provide expicit destructor, the
generated destructor will try destroy the auto_ptr, which in its turn
will try to destroy you pimpl via imcomplete pointer, therefor not
calling destructor. Fortunately compiler at least gives a warning:
"deletion of pointer to incomplete type 'TestClass::PrivateData'; no
destructor called"
Just a small sniplet of working pimpl implementation with shared_ptr:
header file:
---
class TestClass
{
public:
TestClass();
virtual ~TestClass(void);
TestClass(const TestClass& other);
TestClass& operator=(const TestClass& other);
private:
class PrivateData;
boost::scoped_ptr<PrivateData> pd;
};
implementation file:
---
class TestClass::PrivateData
{
//....
};
TestClass::TestClass()
:pd(new PrivateData)
{
}
TestClass::TestClass(const TestClass& other)
:pd(new PrivateData(*other.pd))
{
}
TestClass& TestClass::operator=(const TestClass& other)
{
pd.reset(new PrivateData(*other.pd));
return *this;
}
On 4/27/05, David Gruener
Hi, i'm wondering if there is a nice smart pointer in boost to implement PImpl. I found an implementation here: [1]. So, does boost provide a smart pointer which does play nice with pimpl, so that one doesn't need to provide a destructor, copyconstructor and assignment operator for the default cases?
--David
[1] http://www.octopull.demon.co.uk/arglib/TheGrin.html. _______________________________________________ Boost-users mailing list Boost-users@lists.boost.org http://lists.boost.org/mailman/listinfo.cgi/boost-users
-- Best regards, Zigmar
Pavel Antokolsky aka Zigmar wrote:
And another pitfal with both auto_ptr and shared_ptr (at least on VC7.1 compiler) is if you don't provide expicit destructor, the generated destructor will try destroy the auto_ptr, which in its turn will try to destroy you pimpl via imcomplete pointer, therefor not calling destructor.
shared_ptr will call the destructor in this case.
And another pitfal with both auto_ptr and shared_ptr (at least on VC7.1 compiler) is if you don't provide expicit destructor, the generated destructor will try destroy the auto_ptr, which in its turn will try to destroy you pimpl via imcomplete pointer, therefor not calling destructor. Fortunately compiler at least gives a warning: "deletion of pointer to incomplete type 'TestClass::PrivateData'; no destructor called"
I suppose that a complete type is required to instanciate shared_ptr destructor and any function that will destroy the pointee. I was thinking that shared_ptr does ensure by itself that a complete type is used (contrary to auto_ptr) so that the type must be complete to compile properly. Do you just have a warning meaning that on older compiler someone might not even notice the problem. IMO, the fact that shared_ptr accept incomplete type but require a complete type is what make it interesting for pimpl. Philippe
On 4/29/05, Philippe Mori
And another pitfal with both auto_ptr and shared_ptr (at least on VC7.1 compiler) is if you don't provide expicit destructor, the generated destructor will try destroy the auto_ptr, which in its turn will try to destroy you pimpl via imcomplete pointer, therefor not calling destructor. Fortunately compiler at least gives a warning: "deletion of pointer to incomplete type 'TestClass::PrivateData'; no destructor called"
I suppose that a complete type is required to instanciate shared_ptr destructor and any function that will destroy the pointee.
I was thinking that shared_ptr does ensure by itself that a complete type is used (contrary to auto_ptr) so that the type must be complete to compile properly. Do you just have a warning meaning that on older compiler someone might not even notice the problem.
IMO, the fact that shared_ptr accept incomplete type but require a complete type is what make it interesting for pimpl.
Philippe
I've re-checked the issue with incomplete type, and I see I was wrong. For such class (class without destructor explicitly instantiated): class TestClass { public: TestClass(); // Note there is no destructor // virtual ~TestClass(void); TestClass(const TestClass& other); TestClass& operator=(const TestClass& other); private: class PrivateData; // std::auto_ptr<PrivateData> pd; // boost::scoped_ptr<PrivateData> pd; boost::shared_ptr<PrivateData> pd; }; The results was: auto_ptr - compiled with warning about destroying incomplete type scoped_ptr - failed to compile (thanks to "checked_delete") shared_ptr - compiled and worked - the destructor of TestClass::PrivateData was called (don't know how it works). -- Best regards, Zigmar
Pavel Antokolsky aka Zigmar wrote:
auto_ptr - compiled with warning about destroying incomplete type
As i already mentioned, very little to no benefit here over plain pointer.
shared_ptr - compiled and worked - the destructor of
Yes, but you still have to provide assignment and copy constructor for your standard cases. So, as i stated, little benefit here over plain pointer too and an ideological problem that shared_ptr used in this way, as serveral times suggested, isn't a shared pointer anymore. Again, whats needed is a pointer like Griffiths's grin_ptr or Peter's impl_ptr. I'm looking forward to the policy pointers. --David
participants (10)
-
Caleb Epstein
-
Cory Nelson
-
David Gruener
-
Gennadiy Rozental
-
Jeff Flinn
-
Pavel Antokolsky aka Zigmar
-
Peter Dimov
-
Philippe Mori
-
ray
-
Russell Hind