How can I use shared_ptr of boost in this situation? - c++

I have 2 classes, A and B.
In class A, I have a pointer on B called Bptr.
I allocate memory for Bptr in the constructor of A, and I free memory of Bptr in A's destructor.
class B {
//whatever
public:
B(int,int);
}
class A {
private:
B * Bptr;
public:
A();
}
A::A(){
Bptr = new B(2,5);
}
A::~A(){
delete Bptr;
}
How can I integrate Boost in my code and use the smart pointer : boost::shared_ptr ? How would my code look like?
Thanks a lot!

The first question to ask yourself: why do you want to dynamically allocate the object in the first place? Can you just replace the pointer with a member of type B?
Assuming there is a good reason, then why shared_ptr (rather than scoped_ptr or, in modern C++, unique_ptr)? Why do you need shared ownership?
Once you've answered these questions, and determined that shared ownership is the right solution, just replace B* with a shared pointer, initialise it in the constructor, and get rid of the redundant destructor (assuming it's not needed for anything else).
class A {
private:
boost::shared_ptr<B> Bptr;
public:
A() : Bptr(boost::make_shared<B>(2,5)) {}
};
You could simply initialise it with a pointer, Bptr(new B(2,5)), but using make_shared makes more efficient use of memory and (in more complicated situations than this) makes it easier to ensure exception safety.

class B {
//whatever
public:
B(int,int);
}
class A {
private:
boost::shared_ptr<B> Bptr;
public:
A();
}
A::A(){
Bptr = boost::make_shared<B>(2,5);
}
A::~A(){
// Bptr automatically deleted if this is the only boost::shared_ptr pointing to it
}
Although you could simply use new B(2,5) instead of boost::make_shared<B>, the latter is exception-safe.

Related

Avoid memory leak with delete in C++

I have the following code :
class A{
A(){};
};
class B{
A **a;
public:
B(){
a = new A*[10];
}
~B(){
delete[] a;
}
};
int main()
{
B* b1 = new B();
//delete B;
return 0;
}
I would like to know what is the proper delete for dynamic object b1 in main? From what I understand, we don't need to add a delete in main since the object B as a dynamic array of pointers and calls the destructor on return. Is that right?
we don't need to add a delete in main since the object B as a dynamic array of pointers and calls the destructor on return. Is that right?
No, that's wrong.
If you allocate something with new and don't deallocate that pointer with delete, then the allocation will leak.
P.S. B is very unsafe because it is copyable, but copying it will cause undefined behaviour.
what is the proper delete for dynamic object b1 in main?
b1 isn't a dynamic object. It is a pointer, which points to a dynamic object.
Proper way to manage dynamic allocations is to not use bare owning pointers. Also, you unnecessary dynamic allocation should be avoided. Example:
class B{
std::vector<A*> a;
public:
B() : a(10){}
};
int main()
{
B b;
}
You need to delete if you used new to create an object:
B* b1 = new B();
...
delete b1;
Or, you could use smart pointers, they will call delete for you:
std::unique_ptr<B> b1( new B );
Note: To use unique_ptr, you'll need to include <memory>.

Should I use unique_ptr to keep class' members?

I have such code:
class A
{
public:
A(void);
~A(void)
{
delete b;
delete c;
delete d;
// ...
}
private:
B* b;
C* c;
D* d;
// ...
};
//A.cpp
A(void) : b(new B()), c(new C()), d(new D()) //...
{
}
Class A takes ownership over own objects b, c, d ...
What is the best way to keep these objects? I guess, that usage of std::unique_ptr<B/C/D> type will be suitable for this way. For example, it allows to don't care about carefull writing of destructor.
it allows to don't care about carefull writing of destructor.
More than that.
Your code is not exception-safe. For example, if new D() failed by exception being thrown, delete b and delete c won't be executed and memory will leak, because destructor won't be called if constructor fails. Smart pointers can help you to avoid this kind of situation.
Holding raw pointer as members you need to implement destructor carefully, and copy constructor and assignment etc too. See What is The Rule of Three? and Rule-of-Three becomes Rule-of-Five with C++11?.
Best is to keep everything by value. If it fits*, and does not need to be hidden**. If it does not fit or needs to be hidden first preference is std::unique_ptr***, second preference (if ownership has to be shared) is std::shared_ptr. And only as a last resort (example for which I cannot even think up). You would actually have raw pointers and manage lifetime yourself, with risk of memory errors and leaks.
* - sometimes you want to be able to have parent object on stack by value and child objects are, say, large arrays which, if stored by value would overflow the stack
** - sometimes you don't want to show what child objects really are (because they are complex, say boost.fusion adapted classes. Then you would want some form of PIMPL idiom:
class.hpp
struct b;
struct A { std::unique_ptr<b> b_; A(); ~A(); }
class.cpp:
struct b { ... }
A::A() = default;
A::~A() = default;
*** - automatic management of dynamically allocated members with unique_ptr
struct A {
std::unique_ptr<b> b_;
A(...):
b_(std::make_unique<b>(...)) {}
};
I think it's worth mentioning that if you do not want to transfer ownership, you must use const std::unique_ptr. Using a non-const std:unique_ptr allows to transfer it to another std:unique_ptr.

shared_ptr vs unique_ptr uses in classes and children

I've stared using smart pointer and trying to wrap my head around best uses for it. I've read plenty of articles but I'm confused on which to use in the following example. I've included a shared_ptr and unique_ptrexamples to show what I'm trying to accomplish:
class A
public:
A();
private:
unique_ptr<B> ptrB;
unique_ptr<SomeObject> ptrUnique;
shared_ptr<SomeObject> ptrShared;
A::A()
{
ptrB(new B());
ptrUnique(new SomeObject());
ptrB->PassUnique(ptrUnique);
ptrShared(new SomeObject());
ptrB->PassShared(ptrShared);
}
class B:
public:
void PassUnique(unique_ptr<SomeObject> &ptr_unique);
void PassShared(weak_ptr<SomeObject> &ptr_weak);
void DoSomething();
private:
unique_ptr<SomeObject> ptrUnique;
weak_ptr<SomeObject> ptrWeak;
B::PassUnique(unique_ptr<SomeObject> &ptr_unique)
{
ptrUnique = ptr_unique;
}
B::PassShared(weak_ptr<SomeObject> &ptr_weak)
{
ptrWeak = ptr_weak;
}
B::DoSomething()
{
ptrUnique->SomeMethod();
shared_ptr<SomeObject> ptr1 = ptrWeak.lock();
ptr1->SomeMethod();
}
SomeObject class can be any class. A good example is a database handle that I pass from the parent class A were it was originally initiated to multiple class like B. And from B to C if it exists. My question is if I'm passing a unique_ptr as a reference will setting for example ptrUnqiue = ptr_unique in B:PassUnique create a copy which then is not correct? Or should this be done via shared_ptr? This understanding is what is confusing with smart pointers for me and would appreciate clarification.
Well, this is a question of lifetime. Do you need SomeObject to outlive A? Do B send or is being use outside of this context? You have to decide when your objects dies. If you think SomeObject exists only in this context, I would recommend A to be the owner, as it allocate the resource, and be to old a raw pointer to SomeObject. I would look like this:
class A
public:
A();
private:
unique_ptr<B> ptrB;
unique_ptr<SomeObject> ptrUnique;
};
A::A()
{
ptrB(new B());
ptrUnique(new SomeObject());
ptrB->PassUnique(*ptrUnique);
}
class B:
pubic:
void PassUnique(SomeObject& obj);
void DoSomething();
private:
SomeObject* ptrUnique;
};
B::PassUnique(SomeObject& obj)
{
ptrUnique = &obj;
}
B::DoSomething()
{
ptrUnique->SomeMethod();
}
There is no such thing as
ptrUnique = ptr_unique;
If you need SomeObject to be used and owned outside of this structure, then go with std::shared_ptr like you did. There were no errors with your std::shared_ptr code.
Answer is basically what would be a lifetime of the pointer in the A, B and/or C. Think of it as ranges, [A...a), [B...b) and [C...c). If [B...b) is always within [A...a) and [C...c) is always within [B...b), they have like a Russian dolls hierarchy, then passing down ref-to-ptr is ok. If ranges overlap and changes wildly so you don't really control where last ptr will be destructed and object will be deleted, you'd have to go with shared_ptr.

Pointers to object as class member in "modern C++"

So one rule of thumb I've heard with respect to modern C++ style is that one shouldn't need to use new or delete, and one should instead use smart pointers. So how to go about this when I have a class where one of the members is a pointer to another object. By using a smart pointer I can avoid the need to delete, but I still need to create the object with new. E.g. is the below "canonical" modern C++ style, or how should one go about this?
#include
#include
class B {
public:
B () { std::printf("constructing B\n");}
~B () { std::printf("destroying B\n");}
};
class A {
public:
A ()
{
std::printf("constructing A\n");
b = std::unique_ptr(new B());
}
~A () { std::printf("destroying A\n");}
private:
std::unique_ptr b;
};
int main()
{
A a;
return 0;
}
You use new. There's nothing wrong with using new, it should just be used as rarely as possible.
(delete on the other hand, should almost never be used, since its usage should always be encapsulated in some sort of RAII handle like a smart pointer or a container.)
Note that when using smart pointers, you should always assign the result of new to a named smart pointer or use reset. In your case, you'd want to use:
A() : b(new B()) { }
or:
A()
{
std::unique_ptr<B> x(new B());
b = std::move(x);
}
or:
A() { b.reset(new B()); }
(For why this is important, see the "Best Practices" section of the boost::shared_ptr documentation.)

Why does this dynamic_cast of auto_ptr fail?

#include "iostream"
class A {
private:
int a;
public :
A(): a(-1) {}
int getA() {
return a;
}
};
class A;
class B : public A {
private:
int b;
public:
B() : b(-1) {}
int getB() {
return b;
}
};
int main() {
std::auto_ptr<A> a = new A();
std::auto_ptr<B> b = dynamic_cast<std::auto_ptr<B> > (a);
return 0;
}
ERROR: cannot dynamic_cast `(&a)->std::auto_ptr<_Tp>::get() const
Well, std::auto_ptr<B> is not derived from std::auto_ptr<A>. But B is derived from A. The auto_ptr does not know about that (it's not that clever). Looks like you want to use a shared ownership pointer. boost::shared_ptr is ideal, it also provides a dynamic_pointer_cast:
boost::shared_ptr<A> a = new A();
boost::shared_ptr<B> b = dynamic_pointer_cast<B> (a);
For auto_ptr, such a thing can't really work. Because ownership will move to b. But if the cast fails, b can't get ownership. It's not clear what to do then to me. You would probably have to say if the cast fails, a will keep having the ownership - which sounds like it will cause serious trouble. Best start using shared_ptr. Both a and b then would point to the same object - but B as a shared_ptr<B> and a as a shared_ptr<A>
dynamic cast doesn't work that way. A : public B does not imply auto_ptr<A> : public auto_ptr<B>. This is why boost's shared_ptr provides shared_dynamic_cast. You could write an auto_ptr dynamic cast though:
template<typename R, typename T>
std::auto_ptr<R> auto_ptr_dynamic_cast(std::auto_ptr<T>& in) {
auto_ptr<R> rv;
R* p;
if( p = dynamic_cast<R*>( in.get() ) ) {
in.release();
rv = p;
}
return rv;
}
Just be aware of what happens here. Since auto_ptrs have ownership semantics, a successful downcast means the original more generally typed, auto_ptr no longer has ownership.
The reason is that auto_ptr is not actually a pointer. It's a smart pointer which is a pointer wrapper but not actually a pointer. The type that is passed as a template style argument to dynamic_cast must be a true pointer (or reference) type.
http://msdn.microsoft.com/en-us/library/cby9kycs(VS.80).aspx
You're trying to cast a A* (returned by a.get()) to std::auto_ptr<B>, and since the second is not even a pointer type this fails. Probably you just want to cast it to B*:
std::auto_ptr<A> a(new A());
std::auto_ptr<B> b(dynamic_cast<B*>(a.get()));
This will still not compile, because A and B aren't polymorphic types. A needs to have a virtual function in order to make the types polymorphic. This will compile, but the cast will just throw std::bad_cast, since it isn't really a B*.
And even if it were a B*, it will fail in horrendous ways if you try to use it. Both std::auto_ptrs a and b will assume they own the object and free it later on, resulting in all kinds of memory corruption. You probably want to use a.release() after the cast was successful.
I think c++ stores RTTI (run time type information) in the vtable. Hence to use dynamic_cast<> with an instance object, the object needs have 'vtable'. C++ creates vtable only when at least one function is declared 'virtual' in the class.
The class A and Class B there are no virtual functions. This could be reason for the dynamic_cast failure. Try declaring a virtual destructor in base class.