I have a list pointer in type of A (called ListA) container a vector of pointers B. (Each A object is a container class that has a private attribute: std<vector> *B). Then, I declare a pointer (called C having the same type as A), make a for-loop through ListA to get all pointers B and put them in C. When I quit my program, I deallocate ListA first, ListA in turn deallocates their own vector of pointers B. Then I deallocate pointer C, but the program crashes.
I have debugged this a bit and know that pointer C at the time of deallocation points to nothing, so it doesn't know what to deallocate.
Am I doing wrong? Or what is the solution for my problems?
Sorry, I'll put my code below
//Class A
#pragma once
#include "MyContainer.h"
class B;
class A
{
public:
A();
~A();
MyContainer<B> *pListOfB;
}
A::A()
{
pListOfB = new MyContainer<B>;
}
A::~A()
{
if(pListOfB)
{
delete pListOfB;
pListOfB = NULL;
}
}
//Class C
#pragma once
#include "MyContainer.h"
class B;
class C
{
public:
C();
~C();
MyContainer<B> *pListOfB;
void getListOfB(MyContainer<A> *pListOfA);
}
C::C()
{
pListOfB = new MyContainer<B>;
}
C::~C()
{
if(pListOfB)
{
delete pListOfB;
pListOfB = NULL;
}
}
void C::getListOfB(MyContainer<A> *pListOfA)
{
for(pListOfA->isBegin(); !pListOfA->isEnd();)
{
A *pA = pListOfA->getNext();
for(pA->isBegin(); !pA->isEnd();)
{
B* pB = pA->*pListOfB->getNext();
pListOfB->add(pB);
}
}
}
//Class MyContainer
#pragma once
#include <vector>
template <class T>
class MyContainer
{
public:
MyContainer(void);
~MyContainer(void);
T* getNext();
void removeAll();
void add(T* t);
void isBegin();
bool isEnd();
private:
std::vector<T*> items;
typename std::vector<T*>::iterator it;
};
template <class T> MyContainer<T>::~MyContainer()
{
removeAll();
}
template <class T> void MyContainer<T>::add(T *t)
{
items.push_back(t);
}
template <class T> void MyContainer<T>::removeAll()
{
while(!isEmpty())
{
std::vector<T*>::iterator tempIt =items.begin();
T* t = (*tempIt);
items.erase(tempIt);
delete t;
t=NULL;
}
}
template <class T>
T* MyContainer<T>::getNext()
{
if(isEnd() || isEmpty())
return NULL;
return (T*)(*(it++));
}
template <class T>
void MyContainer<T>::isBegin()
{
it = items.begin();
}
template <class T>
bool MyContainer<T>::isEnd()
{
return it==items.end();
}
I do the following action:
1. Initial a list A object : MyContainer *pListOfA;
2. Insert B data to each A object in pListOfA
3. Initial C object
4. Call C object operation getListOfB to get B data from pListOfA.
5. Quit program
Program first dealloc pListOfA, each A then dealloc their own pListOfB. After that program dealloc C object in turn dealloc pListOfB attribute of C. But pListOfB point to nothing because pListOfA deallocs every data. So my program crash.
I fix by rem the line delete pListOfB in the dtor of class C but I got a warning memory leak at that line.
That's all my problem. Please show me the right way. Thanks in advance.
first, you allocate
then you "take and put" somewhere (not allocating, just copying pointers)
then you deallocate
then you deallocate. ...wait
The right way is not to use plain pointers.
The moment you start to write delete pointer;, you have to reconsider if you really need that pointer and if you do need it, if there is not some pre-packaged smart-pointer class that can take the burden of memory management from you.
The example code you posted can be written entirely without the use of pointers:
//Class A
#pragma once
#include "MyContainer.h"
#include "B.h"
class A
{
public:
A() { };
~A() { };
MyContainer<B> ListOfB;
};
//Class C
#pragma once
#include "MyContainer.h"
#include "B.h"
class C
{
public:
C() { };
~C() { };
MyContainer<B> ListOfB;
void getListOfB(MyContainer<A>& ListOfA);
};
void C::getListOfB(MyContainer<A>& ListOfA)
{
for(ListOfA.isBegin(); !ListOfA.isEnd();)
{
A& anA = ListOfA.getNext();
for(anA.ListOfB.isBegin(); !anA.ListOfB.isEnd();)
{
B aB = anA.ListOfB.getNext();
ListOfB.add(aB);
}
}
}
//Class MyContainer
#pragma once
#include <vector>
template <class T>
class MyContainer
{
public:
MyContainer(void);
~MyContainer(void) { };
T& getNext();
void removeAll();
void add(const T& t);
void isBegin();
bool isEnd();
private:
std::vector<T> items;
typename std::vector<T>::iterator it;
};
template <class T> void MyContainer<T>::add(const T& t)
{
items.push_back(t);
}
template <class T> void MyContainer<T>::removeAll()
{
items.clear();
}
template <class T>
T& MyContainer<T>::getNext()
{
if(isEnd() || isEmpty())
return throw std::out_of_range("");
return *it++;
}
template <class T>
void MyContainer<T>::isBegin()
{
it = items.begin();
}
template <class T>
bool MyContainer<T>::isEnd()
{
return it==items.end();
}
If the B instances need to be shared between class A and class C (the lists in A and C refer both to the same B objects), then you could store shared pointers in the lists.
Related
I am trying to create an app related to Dynamic Arrays. I am trying to get instance calling a function for my array but its giving me the error:
error: call to non-static member function without an object argument
Is there something wrong with the type of getInstance() function?
Here is my header and main file:
dynamic_array.h
#ifndef DYNAMIC_ARRAY_H
#define DYNAMIC_ARRAY_H
template <class T>
class DynamicArray{
private:
T *arr;
static int instance;
public:
int getInstance();
};
template <typename T>
int DynamicArray<T>::getInstance(){
if(instance == 0){
//...
}
return instance;
}
template <typename T>
int DynamicArray<T>::instance = 0;
#endif // DYNAMIC_ARRAY_H
main.cpp
#include "dynamic_array.h"
int main(){
DynamicArray<int> *array = DynamicArray<int>::getInstance(); // Error occurs here
return 0;
}
I guess you are trying to implement design pattern Singleton and a vector (kind of dynamic array) at once.
What about this:
dynamic_array.h
#ifndef DYNAMIC_ARRAY_H
#define DYNAMIC_ARRAY_H
#include <iostream>
template <class T>
class DynamicArray
{
private:
static DynamicArray* instance;
T* arr;
/* singleton pattern
forbid outside access to constructor */
DynamicArray();
DynamicArray(size_t size_of_array);
~DynamicArray();
public:
static void createInstance(size_t size_of_array);
static DynamicArray<T>* getInstance();
static void destroyInstance();
};
template <class T>
DynamicArray<T>* DynamicArray<T>::instance = nullptr;
// singleton methods
template<class T>
inline void DynamicArray<T>::createInstance(size_t size_of_array)
{
if (instance) return;
instance = new DynamicArray(size_of_array);
}
template <typename T>
DynamicArray<T>* DynamicArray<T>::getInstance()
{
// might be nullptr if not initialized
return instance;
}
template<class T>
inline void DynamicArray<T>::destroyInstance()
{
// delete check for nullptr on its own
delete instance;
}
// constructor
template<class T>
inline DynamicArray<T>::DynamicArray(size_t size_of_array)
{
std::cout << "DynamicArray's been constructed.\n";
arr = new T[size_of_array];
}
// destructor
template<class T>
inline DynamicArray<T>::~DynamicArray()
{
delete[] arr;
std::cout << "DynamicArray's destructor has been called.\n";
// instance is still alive
}
#endif
main.cpp
#include "dynamic_array.h"
int main()
{
DynamicArray<int>::createInstance(10);
DynamicArray<int>* instance = DynamicArray<int>::getInstance();
// do something with instance
/* manually call destructor,
so that if more pointers are pointing to instance
they have no access to a delete call */
DynamicArray<int>::destroyInstance();
return 0;
}
I have a World class and a Entity class.
The World class creates new Entites and retuns a pointer to it.
If i use that pointer im never sure if that pointer is still pointing to a valid Entity but i also dont want to use a shared_ptr because the Entity wont get deleted until all shared_ptr are released. So after some time i cameup with this pointer:
#include <iostream>
#include <unordered_map>
template<class T>
class Pointer
{
public:
Pointer() :m_ptr(nullptr){}
Pointer(T*p) :m_ptr(p) { m_ptr->addPtr(this); }
~Pointer() { if(valid()) m_ptr->removePtr(this); }
Pointer(const Pointer &other) :m_ptr(other.m_ptr)
{
if(valid())
m_ptr->addPtr(this);
}
Pointer& operator=(const Pointer& other)
{
if (valid())
m_ptr->removePtr(this);
m_ptr = other.m_pObj;
if (valid())
m_ptr->addPtr(this);
return *this;
}
T* operator->() { return m_ptr; }
T* operator*() { return *m_ptr; }
T* get() { return m_ptr; }
bool valid() { return m_ptr != nullptr; }
private:
template<typename T>
friend class PointerCollector;
T * m_ptr;
};
template <class T>
class PointerCollector
{
public:
PointerCollector() = default;
virtual ~PointerCollector()
{
for (auto &x : m_ptrList)
{
(x.second)->m_ptr = nullptr;
}
}
private:
void addPtr(Pointer<T> *ptr)
{
m_ptrList[ptr] = ptr;
}
void removePtr(Pointer<T> *ptr)
{
m_ptrList.erase(ptr);
}
template<typename T>
friend class Pointer;
std::unordered_map<Pointer<T>*, Pointer<T>*> m_ptrList;
};
class Test : public PointerCollector<Test>
{
public:
Test() {}
~Test() = default;
int getVal() { return m_val; }
private:
int m_val = 100;
};
void func(Pointer<Test> ptr)
{
if (ptr.valid())
{
std::cout << ptr->getVal();
}
else
{
std::cout << "Invalid!\n";
}
}
int main()
{
Test* myTest = new Test();
Pointer<Test> myPtr(myTest);
Pointer<Test> myPtr2(myPtr);
delete myTest;
func(myPtr2);
getchar();
return 0;
}
the Test class will collect the pointers to it and invalidates them if the class gets deleted.
Now i wanted to ask if anyone knows a better implementation or more infomation about this kind of pointer.
I compiled and tested the above code in Visual Studio 2017
The answer is yes, this pattern has been used before by many people. You just created a poor (and broken, because there's at least one outright bug and several things that are sub-optimal) re-implementation of ::std::weak_ptr<T>. You should consider using it instead.
Considering the following code:
class MyClass
{
...
};
template <typename Object>
class List
{
public:
void insert(const Object & x)
{
// call when Object is MyClass
}
void insert(const Object & x)
{
// call when Object is MyClass*
}
}
int main()
{
MyClass a;
List<MyClass> lst;
List<MyClass*> plst;
lst.insert(a);
plst.insert(new Myclass);
return 0;
}
How to tell the compiler call different methods based on if the template is a class or a pointer?
How to fix the code above?
You can use a combination of std::is_pointer and std::enable_if:
#include <type_traits>
#include <iostream>
class MyClass
{
};
template <typename Object>
class List
{
public:
template<class T=Object>
void insert(T t, typename std::enable_if<std::is_pointer<T>::value >::type* = 0)
{
std::cout << "insert pointer" << std::endl;
}
template<class T=Object>
void insert(T t, typename std::enable_if<!std::is_pointer<T>::value >::type* = 0)
{
std::cout << "insert non-pointer" << std::endl;
}
};
int main()
{
MyClass a;
List<MyClass> lst;
List<MyClass*> plst;
lst.insert(a);
plst.insert(new MyClass());
return 0;
}
Live example: https://ideone.com/CK8Zdo
This will allow you to insert both pointers and non-pointers into a pointer or non-pointer list.
If you want to restrict that, you can use this:
#include <type_traits>
#include <iostream>
class MyClass
{
};
template <typename Object>
class List
{
public:
template<class T=Object>
void insert(T t, typename std::enable_if<std::is_same<T,Object>::value&&std::is_pointer<T>::value >::type* = 0)
{
std::cout << "insert pointer" << std::endl;
}
template<class T=Object>
void insert(const T& t, typename std::enable_if<std::is_same<T,Object>::value&&!std::is_pointer<T>::value >::type* = 0)
{
std::cout << "insert non-pointer" << std::endl;
}
};
int main()
{
MyClass a;
List<MyClass> lst;
List<MyClass*> plst;
lst.insert(a);
// plst.insert(a); // compiler error
// lst.insert(new MyClass()); // compiler error
plst.insert(new MyClass());
return 0;
}
Live example: https://ideone.com/3DtBfr
I'm aware that my answer is not exactly about what you are asking, but maybe it could help.
I believe your intention is to have List class with one insert method (not two of them) and behaviour of this method should depend on your template parameter. For this
you could write a specialization of your class for pointers. Then basic template would be used for non pointer types and specialization would be used for pointer types.
Your code would look like this:
template <typename Object>
class List
{
public:
void insert(const Object & x)
{
// call when Object is MyClass
}
};
template <typename Object>
class List<Object *>
{
public:
void insert(Object * x)
{
// call when Object is MyClass*
}
};
void insert(const Object & x)
{
M_insert(x, dispatcher<std::is_pointer<Object>::value> );
}
Inside List use a dispatcher
template <bool B> class dispatcher {};
using ObjectPtr = dispatcher<true>;
using ObjectValue = dispatcher<false>;
then dispatch to M_insert:
void M_insert(const Object &p, ObjectPtr) { // Object is a pointer }
void M_insert(const Object &p, ObjectValue) { // Object is not a pointer }
Live example here. But, I'd encourage you to determine whether you really need that and possibly fix your design accordingly.
This does the trick:
template <typename Object>
class List
{
public:
template<class C = Object>
void insert(const C & x)
{
// call when Object is MyClass
std::cout << "1" << "\n" ;
}
template<class P = Object*>
void insert(P* p)
{
// call when Object is MyClass*
std::cout << "2" << "\n" ;
}
} ;
Here is a working example.
I implemented the following smart pointer template class:
#ifndef __ProjectManager__mSharedPtr__
#define __ProjectManager__mSharedPtr__
#include <stdio.h>
#include "RefCount.h"
template <class T>
class mSmartPtr {
T *data;
RefCount *rc;
public:
mSmartPtr(T* srcPtr);
mSmartPtr(const mSmartPtr&);
~mSmartPtr();
T* operator->() const;
T& operator*() const;
mSmartPtr<T>& operator=( mSmartPtr&);
mSmartPtr<T> operator()(mSmartPtr&);
};
template<class T>
mSmartPtr<T> mSmartPtr<T>::operator()(mSmartPtr<T>& src) {
return dynamic_cast<??>(src);
}
template <class T>
mSmartPtr<T>::mSmartPtr(T *srcPtr):
data(srcPtr) {
rc = new RefCount();
rc->add();
}
template<class T>
mSmartPtr<T>::~mSmartPtr() {
if (rc->remove() == 0) {
delete data;
delete rc;
}
}
template<class T>
mSmartPtr<T>::mSmartPtr(const mSmartPtr<T> &src):
data(src.data), rc(src.rc) {
rc->add();
}
template <class T>
T* mSmartPtr<T>::operator->() const {
return data;
}
template<class T>
T& mSmartPtr<T>::operator*() const {
return &data;
}
template <class T>
mSmartPtr<T>& mSmartPtr<T>::operator=( mSmartPtr<T> &src) {
if (this != &src) {
if (rc->remove() == 0) {
delete data;
delete rc;
}
data = src.data;
rc = src.rc;
rc->add();
}
return *this;
}
#endif /* defined(__ProjectManager__mSharedPtr__) */
let's say my application contains the following classes:
class Base
{
protected:
...
public:
virtual ~Base() =0;
...
};
class Derived1 : public Base
{
protected:
...
public:
virtual ~Derived1() {}
...
};
class Derived2 : public Base
{
protected:
...
public:
virtual ~Derived2() {}
...
};
and I need store data at the following way:
int int main(int argc, char const *argv[])
{
std::vector<mSmartPtr<Base>> v;
mSmartPtr<Derived1> d1 = foo();
v.push_back(d1);
return 0;
}
I need to fix somehow the cast operator, but how? how do I get the base class in the dynamic cast?
#Guvante
Your code did not work , I modified it as follows but I don't know if will work well
template<class T>
mSmartPtr<T> mSmartPtr<T>::operator ()(mSmartPtr<T>& src) {
mSmartPtr<T> retVal(dynamic_cast<T*>(src.data));
retVal.rc = src.rc;
retVal.rc.Add();
return retVal;
}
I think there is a better alternative to this. Unless you have a different location where you need to be able to do this, you can avoid the headache by changing the way you create the object.
int main(int argc, char const *argv[])
{
std::vector<mSmartPtr<Base>> v;
mSmartPtr<Base> d1 = static_cast<Base*>(foo());
v.push_back(d1);
return 0;
}
Just avoid creating an mSmartPtr that is typed differently than your vector.
In your conversion method extract the underlying pointer and cast it then put it into the new smart pointer. Don't forget to copy the RefCount and ensure that your target class has a virtual destructor (so the correct one gets called no matter which smart pointer gets dispossed last).
I couldn't figure out how to define it externally but an inline definition worked.
//In the definition, replacing this line
//mSmartPtr<T> operator()(mSmartPtr&)
template<class Tdest>
operator mSmartPtr<Tdest>() {
mSmartPtr<Tdest> retVal(static_cast<Tdest*>(data));
retVal.rc = rc;
retVal.rc.Add();
return retVal;
}
In theory you could also add a version that takes a r-value if you are using C++11 but I think that would take a little work to do correctly so I avoided it.
[Solved]: The problem was not in template class initialization, but with code-specific issue of using undefined macro inside a template class constructor. The compiler error did not complain about undefined symbol, but was (wrongfully) related to lambdas.
I've searched for an answer but couldn't find an exact one. The closest answer is here: C++ invoke explicit template constructor but I'm not sure if that is entirely related to my question.
And my question is, how can I initialize a member of structure B in initialization list if the member is a template class?
Header ClassA.h:
#ifndef _A_
#define _A_
#include <typeinfo>
#include <windows.h>
template<class Type> class A{
int u,v;
Type** pointer;
public:
A();
A(int number);
~A();
Type& operator[] (int i){
typeid(Type);
return *pointer[i];
}
Type& Get(int i)
{
typeid(Type);
return *pointer[i];
}
Type *GetPointer(int i)
{
typeid(Type);
return pointer[i];
}
Type* add ();
Type& add(Type *element);
Type& add(Type *element, int place);
void expand(int NewLength);
void swap(Type *element, int place);
void remove(int number);
void remove(Type *element);
void removePointer(int number);
void removePointer(Type *element);
};
template<class Type>A<Type>::A(){
u = 128;
v = 10;
}
template<class Type>A<Type>::A(int number){
//some thing to do with number;
u = number;
v = 10;
New( pointer, Type *[u] );
}
template <class Type> A<Type>::~A()
{
}
template <class Type> void A<Type>::expand(int NewLength)
{
Type **NewList = NULL;
NewList = new Type*[NewLength];
}
template <class Type> Type* A<Type>::add ()
{
pointer[u] = new Type;
}
template <class Type> Type& A<Type>::add(Type *element)
{
}
template <class Type> Type& A<Type>::add(Type *element, int place)
{
}
template <class Type> void A<Type>::swap(Type *element, int place)
{
}
template <class Type> void A<Type>::remove(Type *element)
{
}
template <class Type> void A<Type>::removePointer(int nume)
{
}
template <class Type> void A<Type>::removePointer(Type *element)
{
}
#endif
Header StructB.h:
#pragma once
#ifndef _B_
#define _B_
#include "ClassA.h"
struct C{
float x,y,z;
};
struct B{
private:
B(){
}
public:
int x,y;
A<B*> member1;
A<C> member2;
B(int X,int Y) : member1(5),member2(5) {
//initialize x,y
}
void Add(B* otherB){
B** _pOtherB = new B*; (*_pOtherB) = otherB;
member1.add(_pOtherB);
}
};
#endif
The compiler complains with this error (and some other errors, I can post them if nedded):
error C3493: 'number' cannot be implicitly captured because no default capture mode has been specified
Is there any way to do this, or some workaround perhaps?
Thanks in advance :D
Either the code you've given us isn't complete, or it is broken. This line:
New(pointer, Type *[u]);
seems to be referencing either some missing member method or global function, or it is simply invalid. The error message is kinda cryptic, but that's C++ for you.
I'm going to assume that New is some kind of macro, because no normal function (even a templated one) can take this sort of type definition as a parameter. You've not given us the definition of New, so there's no way we can tell. It is probably the absense of this macro (maybe a wrapper for some sort of memory debugging system?) that is causing the crazy error.
If I replace the New line with this:
pointer = new Type*[u];
the code compiles fine.