Reputation: 3632
I know in C++ that a pointer is just that: a pointer to a memory location, and there is no concept of "owners". But consider the following situation (not necessarily good code):
class A {
public:
A(){}
~A()
{ if(myObject!=nullptr)
delete myObject;
}
void createMember()
{myObject=new CrazyCustomClass();}
CrazyCustomClass *getMember()
{return myObject;}
private:
CrazyCustomClass *myObject=nullptr;
}
If it makes a difference, CrazyCustomClass does NOT have a copy constructor, as it makes no sense to copy it. So pretty straight forward - I have a class that, at some point after instantiation, may call new
to instantiate a member of type CrazyCustomClass *
The problem is that if at some point I have a copy of class A
created (which is fine - I want to be able to copy class A
). When that copy is deleted, so is the object pointed to by the original class A instantiation. For example:
void StupidFunction(A *firstObject){
//This is NOT a real function, it simply illustrates the effect of a third-party library function
//create a new object that is a copy of first object
A secondObject(*firstObject);
<do whatever with second object>
//secondObject goes out of scope here and gets deleted.
}
A *firstObject=new A();
firstObject->createMember();
stupidFunction(firstObject);
CrazyCustomClass *customObject=firstObject.getMember(); //this is now an invalid pointer
In the above example, the StupidFunction
is from a third-party library, the idea being that it gives a "temporary" copy of the object that you can work with without messing with the original object, which is good. Class A
and CrazyCustomClass
are both my code and can be changed at will. Unfortunately, when the "temporary" copy is deleted, the way I wrote my destructor causes problems.
My first thought was to use shared_ptr, something like so:
std::shared_ptr<CrazyCustomClass> sharedObject=std::make_shared<CrazyCustomClass>(new CrazyCustomClass);
...but that gave me an error when compiling:
candidate constructor (the implicit copy constructor) not viable: no known conversion from 'CrazyCustomClass *' to 'const CrazyCustomClass' for 1st argument; dereference the argument with *
and if I do dereference the argument with *, it gives me an error about the copy constructor of "CrazyCustomClass"
being deleted, which is true - there is no sensible way to copy CrazyCustomClass
.
So my question is: how can I refactor class A
such that myObject
gets properly deleted when firstObject
goes out of scope, but not when any "temporary" copies of A get deleted?
Upvotes: 0
Views: 249
Reputation: 3632
Using a shared_ptr
is in fact a solution to this problem, however the code as attempted in the original question is incorrect. There are two (at least) different ways to initialize a shared_ptr
(ref: https://msdn.microsoft.com/en-us/library/hh279669.aspx). First, you can do it by using new
as a constructor argument:
shared_ptr<CrazyCustomClass> myObject(new CrazyCustomClass)
Secondly, and this is the generally preferred method, you can use the make_shared function (as attempted in the original post), which takes not the new
object, but the arguments to be passed to the object constructor, in this case nothing:
shared_ptr<CrazyCustomClass> myObject=make_shared<CrazyCustomClass>()
The original code simply got these two methods mixed up, thus the errors about copy constructor: it was trying to instantiate a new CrazyCustomClass
object with a pointer to a CrazyCustomClass
object as the constructor argument.
Once using a shared_ptr
, the delete
in the destructor must be removed.
Tip of the hat to @tkausl and @alterigel for pointing out the error in the comments on the question!
Upvotes: 1