[scoped_ptr] Transferring pointers to scoped_ptr member
Hi, This is just make sure I'm not being too careful in this situation. So please confirm whether this is correct. I have a class with two scoped_ptr members, and I want to pass two pointers to the constructor, which will then transfer the ownership of both to the two member scoped_ptrs. I assume the following is not safe: (I didn't try compiling; using namespace boost and std.) struct B {}; class A { public: A(B* b1, B* b2) : b1_(b1), b2_(b2) {} private: scoped_ptr<B> b1_; scoped_ptr<B> b2_; }; // Create an A this way: A a(new B, new B); Is it correct that this could fail if one of the 'new B's throw, thus leaking before the constructor ever started? If that is so, is this then the correct way to achieve the same in a safe manner? struct B {}; class A { public: A(auto_ptr<B>& b1, auto_ptr<B>& b2) : b1_(b1.release()), b2_(b2.release()) {} private: scoped_ptr<B> b1_; scoped_ptr<B> b2_; }; // Create an A this way: A a(auto_ptr<B>(new B), auto_ptr<B>(new B)); Best regards, Christian
on Sun Aug 17 2008, Christian Larsen
Hi,
This is just make sure I'm not being too careful in this situation. So please confirm whether this is correct.
I have a class with two scoped_ptr members, and I want to pass two pointers to the constructor, which will then transfer the ownership of both to the two member scoped_ptrs. I assume the following is not safe:
(I didn't try compiling; using namespace boost and std.)
struct B {};
class A { public: A(B* b1, B* b2) : b1_(b1), b2_(b2) {} private: scoped_ptr<B> b1_; scoped_ptr<B> b2_; };
// Create an A this way: A a(new B, new B);
Is it correct that this could fail if one of the 'new B's throw, thus leaking before the constructor ever started?
Correct. Please see the guideline at http://www.boost.org/doc/libs/1_36_0/libs/smart_ptr/shared_ptr.htm#BestPract...
If that is so, is this then the correct way to achieve the same in a safe manner?
struct B {};
class A { public: A(auto_ptr<B>& b1, auto_ptr<B>& b2) : b1_(b1.release()), b2_(b2.release()) {} private: scoped_ptr<B> b1_; scoped_ptr<B> b2_; };
// Create an A this way: A a(auto_ptr<B>(new B), auto_ptr<B>(new B));
No, that has the same problem (your auto_ptr's aren't named). the 2nd new could throw before any auto_ptrs are constructed, because the order of evaluation is unspecified. HTH, -- Dave Abrahams BoostPro Computing http://www.boostpro.com
David Abrahams skrev:
on Sun Aug 17 2008, Christian Larsen
wrote: Hi,
This is just make sure I'm not being too careful in this situation. So please confirm whether this is correct.
I have a class with two scoped_ptr members, and I want to pass two pointers to the constructor, which will then transfer the ownership of both to the two member scoped_ptrs. I assume the following is not safe:
(I didn't try compiling; using namespace boost and std.)
struct B {};
class A { public: A(B* b1, B* b2) : b1_(b1), b2_(b2) {} private: scoped_ptr<B> b1_; scoped_ptr<B> b2_; };
// Create an A this way: A a(new B, new B);
Is it correct that this could fail if one of the 'new B's throw, thus leaking before the constructor ever started?
Correct. Please see the guideline at http://www.boost.org/doc/libs/1_36_0/libs/smart_ptr/shared_ptr.htm#BestPract...
Ah yes, that clarifies it. :) Somehow it didn't show up in my search results. But it baffles me, that the order isn't even specified to be "unordered evaluation of the arguments to one function at a time", i.e. as in the example f(shared_ptr<int>(new int(2)), g()); it surprises me that "new int(2)", and then "g()" can be evaluated _before_ the shared_ptr constructor.
If that is so, is this then the correct way to achieve the same in a safe manner?
struct B {};
class A { public: A(auto_ptr<B>& b1, auto_ptr<B>& b2) : b1_(b1.release()), b2_(b2.release()) {} private: scoped_ptr<B> b1_; scoped_ptr<B> b2_; };
// Create an A this way: A a(auto_ptr<B>(new B), auto_ptr<B>(new B));
No, that has the same problem (your auto_ptr's aren't named). the 2nd new could throw before any auto_ptrs are constructed, because the order of evaluation is unspecified.
Ok, so the correct way to do it in the last example is this? auto_ptr<B> b1(new B); auto_ptr<B> b2(new B); A a(b1, b2); A little more verbose than I had hoped, but ok as long as it is doing what it's supposed to.
HTH,
Yes it did, thank you. Best regards, Christian
on Sun Aug 17 2008, Christian Larsen
f(shared_ptr<int>(new int(2)), g());
it surprises me that "new int(2)", and then "g()" can be evaluated _before_ the shared_ptr constructor.
Join the club.
Ok, so the correct way to do it in the last example is this?
auto_ptr<B> b1(new B); auto_ptr<B> b2(new B); A a(b1, b2);
Yep -- Dave Abrahams BoostPro Computing http://www.boostpro.com
2008/8/17 Christian Larsen
class A { public: A(auto_ptr<B>& b1, auto_ptr<B>& b2)
Pass arguments by value here instead of by reference. It's a common idiom that is used to enforce and document the fact that function takes ownership of arguments.
: b1_(b1.release()), b2_(b2.release()) {} private: scoped_ptr<B> b1_; scoped_ptr<B> b2_; };
Roman Perepelitsa.
Roman Elitetroppers skrev:
2008/8/17 Christian Larsen
mailto:contact-AT-dword.dk> class A { public: A(auto_ptr<B>& b1, auto_ptr<B>& b2)
Pass arguments by value here instead of by reference. It's a common idiom that is used to enforce and document the fact that function takes ownership of arguments.
Ah yes, I see. There is of course no indication in this declaration that the function actually calls release on the pointers. But couldn't it possibly result in an extra copy being made? (Unless of course it is optimized away, which I hope it is.) Thanks, Christian
2008/8/18 Christian Larsen
Roman Elitetroppers skrev:
2008/8/17 Christian Larsen
> class A { public: A(auto_ptr<B>& b1, auto_ptr<B>& b2)
Pass arguments by value here instead of by reference. It's a common idiom that is used to enforce and document the fact that function takes ownership of arguments.
Ah yes, I see. There is of course no indication in this declaration that the function actually calls release on the pointers. But couldn't it possibly result in an extra copy being made? (Unless of course it is optimized away, which I hope it is.)
I guess it could. But I would call it 'move' instead of copy, which is cheap. Roman.
participants (3)
-
Christian Larsen
-
David Abrahams
-
Roman Perepelitsa