I am a very new programmer and a super beginner so I don't know too much about c++. I had specifically a question regarding making deep copies of pointers. What I have is a class A full of POD's and a pointer to this class (A *P).
I have a second class B which contains some other POD's and a vector of pointers to Class A.
I want to fill this vector of deep copies of A *P because in a loop I will be dynamically allocating and deallocating it. The following does not work. I believe its my copy constructor and overloading of the = operator. This is something I am doing for fun and learning.
class A
{
public:
.....
.....
.....
};
class B
{
public:
B();
~B();
B(const B &Copier);
B& B::operator=(const B &Overloading);
vector<A*> My_Container;
A* Points_a_lot;
int counter;
};
B::B()
{
counter=0;
Points_a_lot=NULL;
}
B::~B()
{
for(size_t i=0; i<My_Container.size(); i++)
{
delete My_Container[i];
}
}
B::B(const B &Overloading)
{
My_Container[counter]=new A(*Overloading.Points_a_lot);
}
B& B::operator=(const B &Overloading)
{
if(!Overloading.My_Container.empty())
{
Overloading.My_Container[counter]=new B(*Overloading.Points_a_lot);
}
return *this;
}
int main()
{ A* p=NULL;
B Alphabet;
for(....)
{
p=new A;
//some stuff example p->Member_of_A=3; etc..
Alphabet.My_Container[Alphabet.counter]=p;
Alphabet.counter++;
delete p;
}
return 0;
}
Any help will be great. I thank you for your time. Assume needed libraries included.
Okay, it seems to me that you are very confused about what operator= should be doing. Take a look at this page on operator overloading. This should get you started down the right path for that function.
Second, unrelated to your question check out this question about why your fields (member-variables, what-have-you) should be private.
There are many errors in your code. The main one is that your assignment operator and copy constructor are not deep copying a vector of pointers to A at all, rather, you are trying to put a B* in a location of the vector. What your assignment operator should do is to delete the elements the vector points to, and fill it with deep copies of the elements the source object's vector points to, after checking for self assignment. Your copy constructor should be filled with deep copies of the elements of the source objects.
Second, you should provide a method that adds elements to your class' vector, and let it set the counter variable internally. Having to coordinate both the vector and the counter externally is error-prone and one of the advantages of OOP is to avoid that kind of error. But better still, remove the counter variable altogether. You don't need it. YOur main would then be simplified to this:
int main()
{
B Alphabet;
for(....)
{
A* p = new A;
//some stuff example p->Member_of_A=3; etc..
Alphabet.appendElement(p); // B takes ownership, no need to delete in main
}
}
and appendElement could be
class B
{
public:
void appendElement(A* element) { myContainer_.push_back(element); }
// other public methods
private:
std::vector<A*> myContainer_;
};
You could further improve all of this by storing some kind of single ownership smart pointer instead of raw pointers. That would mean you don't have to worry about making deletions yourself. But that is probably beyond the scope of this question.
Now, you should consider avoiding the pointers altogether. In this case, you have to provide no copy constructors, assignment operators or destructors. The compiler-synthesized ones will do just fine. Your class B reduces to
class B
{
public:
void appendElement(const A& element) { myContainer_.push_back(element); }
// other public methods
private:
std::vector<A> myContainer_;
};
I do not fully understand what your requirements are so I attempted to fix the code and do a deep copy of B as that is what it seems you are asking.
#include <vector>
using namespace std;
class A
{
public:
A() : m_someInt(0), m_someFloat(0.0f) {}
// Redundant but putting it here for you to see when it is called (put break-point)
A(const A& a_other)
{
m_someInt = a_other.m_someInt;
m_someFloat = a_other.m_someFloat;
}
int m_someInt;
float m_someFloat;
};
class B
{
public:
B();
~B();
B(const B &Copier);
B& B::operator=(const B &Overloading);
void Cleanup();
void AddA(const A* a);
private:
vector<A*> My_Container;
A* Points_a_lot;
};
B::B()
{
Points_a_lot=NULL;
}
B::~B()
{
Cleanup();
}
B::B(const B &Overloading)
{
// Deep copy B
operator=(Overloading);
}
B& B::operator=(const B &Overloading)
{
// Delete old A's
Cleanup();
// Not using iterators to keep it simple for a beginner
for (size_t i = 0; i < Overloading.My_Container.size(); ++i)
{
// We need new A's which will then copy from the A's in Overloading's container
A* newA = new A( *(Overloading.My_Container[i]) );
// Done with allocation and copy, push_back to our container
My_Container.push_back(newA);
}
return *this;
}
void B::Cleanup()
{
// Assuming B is not responsible for cleaning up Points_a_lot
Points_a_lot = NULL;
for (size_t i = 0; i < My_Container.size(); ++i)
{
delete My_Container[i];
}
// Automatically called when My_Container is destroyed, but here we
// are open to the possibiliy of Cleanup() being called by the client
My_Container.clear();
}
void B::AddA(const A* a)
{
// We are adding a new A. In your code, the incoming A is going to
// be destroyed, therefore, we need to allocate a new A and copy
// the incoming A
A* newA = new A(*a);
My_Container.push_back(newA);
}
int main()
{
A* p=NULL;
B Alphabet;
for(int i = 0; i < 10; ++i)
{
p = new A();
//some stuff example p->Member_of_A=3; etc..
Alphabet.AddA(p);
delete p;
}
// If you put a breakpoint here and step through your code, you will see
// `B` deep-copied
B NewAlphabet = Alphabet;
return 0;
}
A few notes:
Newing and deleteing A in the loop is a bad idea. I realize you are doing this just to learn, which is great, but you may want to keep this in mind. Instead of destroying A through p, allow B to take ownership of the new A
Step through the code by using a debugger to see how it works
Try to post code that is as close to your original as possible when asking "why doesn't this work/compile"
Looks like you should instead have your My_Container consist of unique_ptrs so that when you assign, that the vector takes over ownership of the A instance
for(....)
{
p=new A;
//some stuff example p->Member_of_A=3; etc..
Alphabet.My_Container[Alphabet.counter]=p;
Alphabet.counter++;
delete p;
}
so instead declare My_Container as
vector<std::unique_ptr<A*> > My_Container;
then the code will be
for(....)
{
p=new A;
//some stuff example p->Member_of_A=3; etc..
Alphabet.My_Container[Alphabet.counter]=p;
Alphabet.counter++;
}
then if you need to do a 'deep copy' create a member in A called clone() or something and return a unique_ptr to the instance, use that when you need to create a copy.
You may want to take a look at boost::ptr_vector. Its interface is very similar to that of a std::vector but it is tailored for pointers and thus:
owns the resources (so no memory leak)
allow polymorphic storage (derived classes)
is const-correct and copy-correct
In order for the copy to work, you'll have to provide a A* new_clone(A const*) implementation.
Related
I want to take an instance of BaseClass which was creating using the BaseClass constructor and upgrade it to an instance of Inherited. I know that the Inherited class needs a separate block of memory allocated for it and that the original BaseClass instance should be freed.
This is a (seemingly) working example of this.
class BaseClass{
public:
BaseClass(int mem1, int mem2){
this->mem1 = mem1;
this->mem2 = mem2;
}
BaseClass(BaseClass* base){
this->mem1 = base->mem1;
this->mem2 = base->mem2;
}
virtual ~BaseClass(){
printf("Deconstruct Base\n");
}
private:
int mem1;
int mem2;
};
class Inherited: public BaseClass{
public:
Inherited(int mem1, int mem2, int mem3): BaseClass(mem1, mem2){
this->mem3 = mem3;
}
Inherited(BaseClass* base, int mem3): BaseClass(base){
this->mem3 = mem3;
free(base); // this doesn't print 'Deconstruct Base'
}
~Inherited(){
printf("Deconstruct Inherited\n");
}
int mem3;
};
int main(){
BaseClass* p = new BaseClass(1, 2);
p = new Inherited(p, 3);
// this prints 'Deconstruct Inherited' then 'Deconstruct Base'
delete p;
}
So in the constructor for my Inherited class, I use free to deallocate the memory of the original instance of BaseClass.
The goal of this is that if BaseClass has a pointer to a large block of dynamically allocated memory, I would like the Inherited class to pick up that pointer instead of letting BaseClass deallocate it.
My questions are:
Would this leak memory for any reason?
Is there a cleaner way to do this? (for example: would calling operator delete be a better option than free? Or is there a better solution entirely?)
You can't change the type of an object, so it's a bit hard to know what "upgrade an object" is intended to mean. But judging from the code, it's more or less "copy the data from the original object into a new one and get rid of the original object". That's easy:
class base {
public:
base(int m) : mem1(m) {}
base(const base&) = default;
private:
int mem1;
};
class derived : public base {
public:
derived(int m1, int m2) : base(m1), mem2(m2) {}
derived(const base* b, int m2) : base(*b), mem2(m2) {}
private:
int m2;
};
base* bp = new base(3);
base* temp = bp;
bp = new derived(temp, 4);
delete temp;
If that's too verbose you can write a function with a descriptive name:
void replace_object(base*& bp, int m2) {
base* temp = bp;
bp = new derived(temp, m2);
delete temp;
}
and now you can write
base* bp = new base(3);
replace_object(bp, 4);
If you really, really want to hide all this stuff (maintainers will hate you), you can do the delete in the constructor for derived:
derived(const base* b, int m2) : base(*b), mem2(m2) {
delete b;
}
and now you can write
base* bp = new base(3);
bp = new derived(bp, 4);
You code has a lot of issues.
I suggest you to read books on writing good code like Exceptional C++ from Sutter.
Issue 1: Use the initialization list whenever appropriate.
BaseClass(int mem1, int mem2)
: mem1(mem1)
, mem2(mem2)
{
}
Inherited(int mem1, int mem2, int mem3)
: BaseClass(mem1, mem2)
, mem3(mem3)
{
}
This would be more efficient for user defined types and required for
types that does not support assignation (constant and reference
members among others).
Always initialize those members in declaration other.
Issue 2: Define standard copy constructor (instead of your own variation)
BaseClass(const BaseClass &other)
: mem1(other.mem1)
, mem2(other.mem2)
{
}
Even better. In this case, you can use default copy constructor.
BaseClass(const BaseClass &other) = default;
Issue 3: If you define the copy constructor, you should define the assignment operator too.
BaseClass& operator=(const BaseClass &other) = default;
You could also define move constructor and assignment as necessary.
Issue 4: You should never call free on an object allocated with new.
Issue 5: I most case, you should avoid transferring ownership through a constructor.
This is error prone as this is not what user are expecting. This make the code harder to maintain and if you are not careful, this can be a source of memory leak if an exception is throw from the constructor.
Inherited(const BaseClass &b, int m3)
: BaseClass(b)
, mem3(m3)
{
}
Issue 6: If you really want to transfer ownership, then you should use std::unique_ptr to make it clear that you are transferring it.
Inherited(std::uniquer_ptr<BaseClass> b, int m3)
: BaseClass(*b)
, mem3(m3)
{
}
And at call site, something like:
std::unique_ptr<BaseClass> p = std::make_unique<BaseClass>(1, 2);
std::unique_ptr<Inherited> q = std::make_unique<Inherited>(std::move(p), 3);
// at this point, p is null since ownership has been moved
p = q;
I think that with recent version of C++, you could do the replacement in place instead of using a temporary variable.
Issue 7: You should avoid explicit memory management as it is error prone.
See issue 6 for code.
Or as it this case allocating memory is useless. Code like that would be far more optimal:
Base b(1, 2);
Inherited i(b, 3);
// Use i (by reference) from that point…
If b is not need anymore afterward, you could also write something like:
Inherited i2(Base(1, 2), 3);
At which point, why not write:
Inherited i3(1, 2, 3);
Issue 8: There is no such things are upgrading object type. You are simply assigning a new value to a pointer which is based on the old object.
And actually replacing an object would cause object slicing in your case.
I have abstract class Figure. Then I have an array of it, and I want to resize it, but not sure how to do it.
Figure ** arr; //lets assume it's filled with some data
Figure ** temp = new Figure * [size + 1];
for(int i =0; i < size; ++i)
{
temp[i] = new Figure(); //it doesn't let me to create object from the abstract class
temp[i] = arr[i] //if I do this, once I delete arr, I will lose temp as well
}
Any help?
The problem
If Figure is an abstract class, you can't instantiate it:
temp[i] = new Figure(); // ouch: can't do: strictly forbidden
and even if you could, you couldn't copy such a polymorphic class without suffering from slicing:
temp[i] = arr[i]; // arr[i] is a derivate of Figure and might have a different size for example
The solution
To solve your issue, you must define a virtual clone() member function:
class Figure {
...
Figure* clone() = 0;
};
You would then implement this function, for example like this:
class Square : public Figure {
...
Figure* clone() override {
return new Square(*this);
}
};
You would change your deep copy to to:
temp[i] = arr[i].clone();
The improvement
The risk of returning a freshly allocated clone is to have a memory leak. So
instead of using raw pointers you could use shared_ptr<Figure> or unique_ptr<Figure> (not only as return argument of the cloning function but also as element of the array.
By the way, you could also consider changing the array to a vector, thus avoiding extra manual memory allocation (and later deletion) of the temp.
The answer is to take advantage of the polymorphic behavior the class hierarchy provides and make a virtual function to create the copy. For example, clone is a commonly named function for this.
Example Code
#include <iostream>
#include <memory>
#include <vector>
class Base
{
public:
virtual ~Base() {}
virtual Base* clone() const = 0;
virtual void print() const = 0;
};
class D1 : public Base
{
public:
virtual D1* clone() const override { return new D1(*this); }
virtual void print() const override { std::cout << "D1\n"; }
};
class D2 : public Base
{
public:
virtual D2* clone() const override { return new D2(*this); }
virtual void print() const override { std::cout << "D2\n"; }
};
int main()
{
std::vector<std::unique_ptr<Base>> original;
original.push_back(std::make_unique<D1>());
original.push_back(std::make_unique<D2>());
std::vector<std::unique_ptr<Base>> copy;
for (const auto& o : original)
{
copy.push_back(std::unique_ptr<Base>(o->clone()));
}
for (const auto& c : copy)
{
c->print();
}
return 0;
}
Example Output
D1
D2
Live Example
All of this can be achieved just the same with C style arrays however this question is tagged with C++.
Note: Even though the derived classes have a different signature for their respective clone functions this is perfectly valid. See covariant return type for more information.
On my work I have met with one bug which can be described as follows.
There are two classes, class A and class B:
class A
{
public:
void print(){}
};
class B
{
A* a;
public:
void init(A* _a) {
a = _a;
}
void PrintWithA()
{
a->print();
}
};
A* a;
B* b;
b->init(a);
// some code .....
delete a; // line 1
a = NULL;
// some code .....
b->PrintWithA(); // line 2
Object "b" doesn't know nothing about state of object "a". In line 1 "a"object has been deleted but on line 2 we continue to use it. When there are a lot of code it is very easy to make such mistake.
My question is the following - which approch to use to avoid some mistakes? I guess I could use observer pattern - but I think it is unjustifiably expensive solution.
Thank's.
You should use a weak ptr (http://en.cppreference.com/w/cpp/memory/weak_ptr)
basically you can provide class B with a weak ptr of A.
whenever comes time to access A, you can try to lock the weak ptr to see if it's still valid.
#include <memory>
class A
{
public:
void print(){}
};
class B
{
std::weak_ptr<A> a;
public:
void init(std::weak_ptr<A> _a) {
a = _a;
}
void PrintWithA()
{
if (auto spt = a.lock()) {
spt->print();
}
}
};
int main()
{
std::shared_ptr<A> a = std::make_shared<A>();
std::unique_ptr<B> b = std::make_unique<B>();
b->init(a);
// some code .....
a = nullptr;
// some code .....
b->PrintWithA(); // line 2
return 0;
}
To guard against that, either B needs to take ownership of the lifetime of A when the object B is constructed, or you need to make A reference counted.
C++11 I think has the concept of a shared pointer which maintains the references and will prevent the object A from being deleted if someone has a reference. See std::shared_ptr
If you are not using C++11 there is boost::shared_ptr which does essentially the same thing. But you need the boost library which I personally prefer not to use, but it's up to you.
Use them like this:
typedef std::shared_ptr<A> A_ptr;
A_ptr a = new A();
class B
{
A_ptr a;
public:
void B(A_ptr _a) {
a = _a;
}
void PrintWithA()
{
a->print();
}
};
Otherwise you could put something together yourself. Something along the lines of:
class A
{
public:
A(){
ref_count = 1;
}
void print(){}
void grab() {
ref_count++;
}
void release() {
ref_count--;
if (ref_count <= 0)
~A();
}
private:
int ref_count;
~A(){
delete this;
}
};
Inside B you'd assign the pointer and call grab();
Rather than call delete (which wouldn't work because it's private) you'd call
a->release() on the pointer.
Now this is not particularly fantastic because you can't use this form:
A a;
So it's not ideal. But if you're using some compiler that doesn't have a shared_ptr and you don't mind the limitation you may use this or a form of it. In general, use shared_ptr.
First of all, the line that says A* a; should probably be A* a = new A;.
In c++ you need to encode this awareness explicitly, it's not done automatically.
One thing you can do is check if _a is NULL inside PrintWithA, but this won't work if you make sure that you always set your pointers to NULL after delete[]ing them (which you've done)
I'm a newbie using V++ and I've been wondering about some memory behavior.
I wrote similar classes to what is causing me problems. The questions are
written in the comments of the code.
class A
{
private:
int _number;
public:
A(int number) : _number(number)
{}
const int& getNumber() const
{
return _number;
}
void setNumber(const int& number)
{
_number = number;
}
}
class B
{
private:
A _a;
bool _hasA;
public:
B() : _hasA(false)
{}
B(const A & a) : _a(a), _hasA(true)
{}
void setA(const A & a)
{
_a = a;
}
const A& getA() const
{
return _a;
}
const bool hasA() const
{
return _hasA;
}
void removeA()
{
// ??
}
}
int main()
{
A a(5);
B b1; // Is the A space allocated even if no value is affected to it ?
B b2(a);
b1.setA(b2.getA()); // I actually want to move "a" from b2 to b1 without leaving it in b2
b1.removeA(); // Do I need to write a removeA() function and how would it be?
}
b1.setA(b2.getA()); copies A into b1 too instead of moving it.
Thanks for your help.
EDIT: To answer those who are confused like I just was:
Me : I just understood that when instanciating b1 it needed the A::A() constructor. I thought it'd be like "null" or something if I created b1 without instantiating _a.
Zac Howland: #SanjamX I see your confusion now. In managed languages, (most) everything is a pointer, so if you do not instantiate it (e.g. A a instead of A a = new A()), it is just a null pointer. In C/C++, if you declare something as A a, you instantiated it "on the stack". It is an automatic variable that will be deallocated when it goes out of scope. You are still instantiating it, however. This question may help you understand better.
B b1();
That does not do what you think it does. It is declaring a function b1 that takes no parameters and returns a B.
b1.setA(b2.getA());
b1.removeA();
Because of the previous situation, the 2 lines above will give you a compiler error.
The "move" you are asking about will actually be a copy (in this case). You can use the C++11 move semantics to do an actual move, but it is entirely unnecessary with the current code. Alternatively, you can change your class to do a move using pointers (which could potentially be useful) - which would use std::unique_ptr<A> _a, instead of A _a.
just for the sake of experimentation, I'm playing with the singleton pattern. I was wondering if it could be possible to extend the usual singleton class
class A
{
private:
static A* m_instance;
A();
public:
static A* GetInstance();
}
A::A(){ ...some code}
A* A::m_instance = NULL;
A* A::GetInstance()
{
if( m_instance == NULL ) m_instance = new A();
return m_instance;
}
to a "multiple singleton" class, something like
class B
{
private:
static vector<B*> m_instances;
B();
public:
static B* GetInstance( unsigned int n = 0);
static B* GetNewInstance();
}
B* B::GetInstance( int n)
{
if( n < m_instances.size() ) return m_instances.at(n);
//Create a new instance and append it to m_instances
B * temp = new B();
m_instances.push_back( temp );
return temp;
}
B* B::GetNewInstance()
{
B * temp = new B();
m_instances.push_back( temp );
return temp;
}
The main problem I find in this pattern is the implementation of the destructor, because each nstance contains the vector of the instances so, if I delete an instance, I delete also the vector containing all other instances.
Is it possible to make this work? Or is it just a wrong pattern, plain and simple?
I assume you know that Singleton are smells of a bad design. See What is so bad about singletons?
To answer your question, you're right about the drawbacks of a "multiple singleton". A better design would be instead a singleton where the variable is a vector<A*>, or vector<unique_ptr<A>> if you're using C++11 (assuming each A can't be copied and needs to be instantiated once. Otherwise use vector<A>)
because each nstance contains the vector of the instances so, if I delete an instance, I delete also the vector containing all other instances.
No the vector<B*> will exist once for all instances since you've declared it static.
Who should call delete of your instances when? Usually using your technique the destructors of the singleton instance(s) never will be called.