My abstract Reference counter class:
template<class T>
class ReferenceCounter
{
public:
ReferenceCounter();
~ReferenceCounter();
void addRef();
void release();
uint32 getCountReferences() const;
protected:
int32* pCountReferences;
virtual void destroyObject() = 0;
virtual void shallowCopy(const T& rhs) = 0;
};
template<class T>
inline ReferenceCounter<T>::ReferenceCounter()
{
pCountReferences = new int32;
*pCountReferences = 1;
}
template<class T>
inline ReferenceCounter<T>::~ReferenceCounter()
{
if(pCountReferences != NULL && *pCountReferences == 0)
{
delete pCountReferences;
pCountReferences = NULL;
}
}
template<class T>
inline void ReferenceCounter<T>::addRef()
{
debug_assert((*pCountReferences) >= 0, "Incorrect value of count references");
++(*pCountReferences);
}
template<class T>
inline void ReferenceCounter<T>::release()
{
debug_assert((*pCountReferences) > 0, "Incorrect value of count references");
(*pCountReferences)--;
if(pCountReferences != NULL && *pCountReferences == 0)
{
destroyObject();
}
}
template<class T>
inline uint32 ReferenceCounter<T>::getCountReferences() const
{
return *pCountReferences;
}
This is my smart pointer :
template<class T>
class SmartPtr
{
public:
SmartPtr();
SmartPtr(T* pInst);
SmartPtr(const SmartPtr<T>& rhs);
~SmartPtr();
void operator = (const SmartPtr<T>& rhs);
T* operator -> () const;
T* getData() const;
bool isNULL() const;
private:
T* pInst;
};
template<class T>
SmartPtr<T>::SmartPtr() : pInst(NULL) {}
template<class T>
SmartPtr<T>::SmartPtr(T* pInst) : pInst(pInst) {}
template<class T>
SmartPtr<T>::~SmartPtr()
{
if(pInst != NULL)
{
pInst->release();
}
}
template<class T>
SmartPtr<T>::SmartPtr(const SmartPtr<T>& rhs)
{
this->pInst = rhs.pInst;
if(pInst != NULL)
{
pInst->addRef();
}
}
template<class T>
void SmartPtr<T>::operator= (const SmartPtr<T>& rhs)
{
this->pInst = rhs.pInst;
if(pInst != NULL)
{
pInst->addRef();
}
}
template<class T>
T* SmartPtr<T>::operator->() const
{
return pInst;
}
template<class T>
T* SmartPtr<T>::getData() const
{
return pInst;
}
template<class T>
bool SmartPtr<T>::isNULL() const
{
return pInst == NULL;
}
There are test of code :
#include <iostream>
#include "ReferenceCounter.h"
#include "SmartPtr.h"
using namespace std;
class B;
class A : public ReferenceCounter<A>
{
public:
A();
A(const A& rhs);
~A();
SmartPtr<B> getB();
void operator = (const A& rhs);
private:
void destroyObject();
void shallowCopy(const A& rhs);
};
class B : public ReferenceCounter<B>
{
private:
void destroyObject() {} ;
void shallowCopy(const B& rhs) {};
};
A::A()
{
cout << "Create object" << endl;
}
A::A(const A& rhs)
{
shallowCopy(rhs);
addRef();
cout << "copy constructor " << endl;
}
A::~A()
{
release();
}
void A::destroyObject()
{
cout << "destroy" << endl;
}
void A::shallowCopy(const A& rhs)
{
this->pCountReferences = rhs.pCountReferences;
}
void A::operator = (const A& rhs)
{
shallowCopy(rhs);
addRef();
cout << "operator = " << endl;
}
SmartPtr<B> A::getB()
{
return SmartPtr<B>(new B());
}
SmartPtr<A> getA()
{
SmartPtr<A> a(new A());
return a;
}
int main()
{
getA();
return 0;
}
This code is worked but below not called copy constructor of smart pointer when i debug this code . What problems happens below ??
int main()
{
A a;
a.getB();
}
See here for Return value optimization.
The compiler is allowed, to eliminate the copy of a temporary object being returned.
With C++11, there's also the possibility of moving an object. See What are move semantics? for an explanation.
Update:
This is not a problem at all, just a compiler optimization.
As long as there's nothing special going on in your constructor and destructor, there's no need to prevent this optimization. You should allow this instead, because it makes your program run faster by skipping one constructor and one destructor call.
Related
Got this code (should be all that is relevant):
//movable_ptr.hpp
//Michal Cermak
#ifndef MOVABLE_H
#define MOVABLE_H
template<typename T> class movable_ptr;
template<typename T> class enable_movable_ptr {
public:
//default constructor
enable_movable_ptr() {};
enable_movable_ptr(T* p) : ptr_(p) {};
//operators...
T& operator*() const { return *ptr_; };
T* operator->() const { return ptr_; };
bool operator==(const enable_movable_ptr<T>& p) const { return p.ptr_ == ptr_; };
T* get() {return ptr_; };
private:
T* ptr_ = nullptr;
};
template<typename T> class movable_ptr {
public:
//parameterless constructor
movable_ptr() {};
//constructor from T*
movable_ptr(T* p) : ptr_(p) { add_to_tracked(this); };
//operators ...
enable_movable_ptr<T>& operator*() const { return *ptr_; };
enable_movable_ptr<T>* operator->() const { return ptr_; };
bool operator==(const movable_ptr<T>& p) const { return p.ptr_ == ptr_; };
//access to variables
enable_movable_ptr<T>* get() {return ptr_; };
void set(enable_movable_ptr<T>* p) { ptr_ = p; };
private:
enable_movable_ptr<T>* ptr_ = nullptr;
};
template<typename T> movable_ptr<T> get_movable(enable_movable_ptr<T>& p){
return new movable_ptr<T>(p);
};
#endif
My problem is that when I run the following code (or other similar ones for that matter), the movable_ptr<T> doesn't get de-referenced all the way to A, but gets stuck on enable_movable_ptr<A>, which causes comparisons and other stuff to throw errors, because "'val' is not a member of enable_movable_ptr<A>". It is a member of A though, so if I de-reference correctly, it should then work.
#include <iostream>
#include <memory>
#include <string>
#include "movable_ptr.hpp"
using namespace std;
class A : public enable_movable_ptr<A>
{
public:
int val;
A(int val) : val(val) {}
};
void test_ptr_dereference() {
A x(42);
auto px = get_movable(x);
TEST_ASSERT(&*px == &x);
TEST_ASSERT(&px->val == &x.val);
}
int main(int argc, char* argv[]) {
test_ptr_dereference();
}
I am guessing I did something wrong in the overloaded operators, but otherwise have no clue. Any ideas on how to fix it?
Here is the deal:
I have a templated class C
template<class T>
class C;
that has a member that is basically a pointer to a reinterpretation of T called P (don't worry about P)
P* reint;
what I want to do is a method that receives a T and copies it into reint
void foo (T& param) {
new (reint) (param);
}
problem is the compiler is giving out warnings that reint is not a T that I want to get rid of. My first idea was to reinterpret reint into a T:
void foo (T& param) {
new (reinterpret_cast<T&>(*reint)) T(param);
}
but the compiler started giving me an error saying
invalid conversion from const void* to void*
So i looked it up and new is defined as such:
void* operator new (std::size_t size, void* ptr) throw();
So for some reason my casting is turning reint into a const void*.
New idea: cast reint to a T and call the copy constructor. Problem: no clue how to call the copy constructor from an unknown class.
(maybe
reinterpret_cast<T>(*reint).T(param);
?)
Could you help me please?
Maybe you want something like:
#include <stdexcept>
struct Data
{
const std::string value;
Data(const std::string& value)
: value(value)
{}
Data(const Data& other) = default;
Data& operator = (const Data& other) = delete;
};
template <typename T>
class Holder
{
public:
Holder() = default;
Holder(const T& data) {
assign(data);
}
~Holder() {
release();
}
void assign(const T& data) {
release();
new (m_data) T(data);
m_valid = true;
}
void release() {
if(m_valid) {
reinterpret_cast<T*>(m_data)->~T();
m_valid = false;
}
}
const T& get() const {
if( ! m_valid) throw std::runtime_error("Invalid");
return *reinterpret_cast<const T*>(m_data);
}
private:
bool m_valid = false;
char m_data[sizeof(T)];
};
#include <iostream>
int main() {
Holder<Data> holder;
holder.assign(Data("Hello"));
const Data& data = holder.get();
std::cout << data.value << '\n';
}
You're going the wrong way, you want somethng more like:
reint = reinterpret_cast<P*>(param);
The solution was to make a struct to return the reinterpreted P for both const and unconst
template <class T> struct Temp {
T* switch (P* r) { return reinterpret_cast<T*>(r); }
}
template <class T> struct Temp <const T> {
T* switch (P* r) { return reinterpret_cast<T*>(r); }
}
then use the struct to remove const from reint
new (Temp::switch(reint)) T(param);
unique_ptr is quite useful. However, it is not copyable. If virutal clone (deep copy) methods are provided for its pointed class, I think it will become more useful. Is it necessary or any better way to implement it? Any similar smart pointer exist in some library? Here is a version
template<class T>
class deep_ptr: private unique_ptr<T>
{
public:
using unique_ptr<T>::operator *;
using unique_ptr<T>::operator ->;
using unique_ptr<T>::operator bool;
using unique_ptr<T>::release;
using unique_ptr<T>::reset;
using unique_ptr<T>::get;
// add (DEFAULT_CONSTRUCTOR)(MOVE_CONSTRUCTOR)(MOVE_ASSIGNMENT_METHOD) ...
explicit deep_ptr(T* p) : unique_ptr(p) {}
deep_ptr(deep_ptr const& r) : unique_ptr(r->clone()) {}
deep_ptr& operator=(deep_ptrconst& r)
{ if (this != &r) reset(r->clone()); return *this; }
};
Juse feel it is very useful but never see similar things. ???
Unless I am misunderstanding what you are looking for, if a class has a clone method, that should be sufficient to get what you are looking for.
Sample code:
#include <iostream>
#include <memory>
struct A
{
virtual ~A() {}
virtual A* clone() = 0;
};
struct B : A
{
B(int in = 0) : x(in) {}
B(B const& copy) : x(copy.x) {}
virtual ~B() {std::cout << "In B::~B()\n";}
virtual A* clone() { return new B(*this); }
int x;
};
int main()
{
std::unique_ptr<A> p1(new B(10));
std::unique_ptr<A> p2(p1->clone());
return 0;
}
Output from running the above program:
In B::~B()
In B::~B()
Without a clone method (just a copy-constructor) the following should work:
template <typename T>
class deep_ptr
{
public:
deep_ptr() : i_() {}
deep_ptr(std::nullptr_t) : i_(nullptr) {}
template <typename U>
deep_ptr(U* u) : i_(u ? new inner_impl<U>(*u) : nullptr) {}
~deep_ptr() { delete i_; }
deep_ptr(const deep_ptr& p) : i_(p.i_ ? p.i_->copy() : nullptr) {}
deep_ptr& operator=(const deep_ptr& p)
{
if (!p.i_) { i_ = nullptr; }
else { i_ = p.i_->copy(); }
}
deep_ptr(deep_ptr&& p) : i_(p.i_) { p.i_ = nullptr; }
deep_ptr& operator=(deep_ptr&& p)
{
i_ = p.i_;
p.i_ = nullptr;
}
const T* operator->() const { return get(); }
const T* get() const
{
if (i_) { return *i_; }
return nullptr;
}
const T& operator*() const { return *static_cast<T*>(*i_); }
T* operator->() { return get(); }
T* get()
{
if (i_) { return *i_; }
return nullptr;
}
T& operator*(){ return *static_cast<T*>(*i_); }
private:
struct inner
{
virtual inner* copy() const = 0;
virtual operator const T*() const = 0;
virtual operator T*() = 0;
virtual ~inner() {}
};
inner* i_;
template <typename U>
struct inner_impl : inner
{
inner_impl(const U& u) : u_(u) {}
inner_impl* copy() const override { return new inner_impl(u_); }
operator const T*() const override { return &u_; }
operator T*() override { return &u_; }
U u_;
};
};
I'm attempting to re-create the any that is found in Boost::any and I have built the three classes, however, whenever I come to reinterpret_cast for the value that is given, the output is completely different and just throws out garbage. Here is my code below:
namespace Types {
class PlaceMaker {
public:
PlaceMaker() { };
virtual ~PlaceMaker()
{
}
virtual PlaceMaker * clone()
{
return 0;
}
virtual const std::type_info & type() const = 0;
protected:
};
template<typename T>
class holder : public PlaceMaker {
public:
holder(const T & value)
: held(value)
{
}
virtual const std::type_info & type() const
{
return typeid(T);
}
virtual PlaceMaker * clone() const
{
return new holder(held);
}
T retrunHeld() const {
return held;
}
public:
T held;
//holder &operator=(const holder &) const = 0;
holder & operator=(const holder &) { }
};
class Any : PlaceMaker {
public:
Any() : maker(0) { };
template<typename ValueType>
Any(const ValueType & value)
: maker(new holder<ValueType>(value))
{
}
Any(const Any & other)
: maker(other.maker ? other.maker->clone() : 0)
{
}
Any& swap(Any &rhs) {
std::swap(maker, rhs.maker);
return *this;
}
template<typename ValueType>
Any & operator=(const ValueType & rhs)
{
Any(rhs).swap(*this);
return *this;
}
Any & operator=(Any rhs)
{
rhs.swap(*this);
return *this;
}
bool empty() const
{
return !maker;
}
const std::type_info & type() const
{
return maker ? maker->type() : typeid(void);
}
template<typename T>
T& cast() {
T* r = reinterpret_cast<T*>(maker);
return *r;
}
public:
PlaceMaker * maker;
};
In main I have the following:
int main() {
Types::Any a = 10;
std::cout << a.cast<int>();
}
// output: 96458224
Could anyone tell me as to where I'm going wrong?
Thanks
You're casting a Holder* to a T*. Given that Holder has virtual functions in it, that means you're gonna be looking at the vtable, not the T itself.
Not 100% sure whether my question is worded correctly as I don't fully understand my problem.
For my course I need to create my own smart pointer to clean up after itself.
Here's my code so far:
Header:
class Test
{
public:
Test()
{
m_iTest1 = 4;
m_iTest2 = 3;
m_iTest3 = 2;
m_iTest4 = 1;
}
Test (int a, int b, int c, int d)
{
m_iTest1 = a;
m_iTest2 = b;
m_iTest3 = c;
m_iTest4 = d;
}
Test(const Test& a_oTest)
{
m_iTest1 = a_oTest.m_iTest1;
m_iTest2 = a_oTest.m_iTest2;
m_iTest3 = a_oTest.m_iTest3;
m_iTest4 = a_oTest.m_iTest4;
}
~Test(){;}
int m_iTest1;
int m_iTest2;
int m_iTest3;
int m_iTest4;
};
template<class T>
class SmartData
{
public:
template<class T> friend class SmartPointer;
SmartData();
SmartData(const T& a_oData);
~SmartData();
T operator * () const;
unsigned int GetCount(){return m_uiCount;}
protected:
void IncrementCount(){++m_uiCount;}
void DecrementCount();
void DeleteThis();
unsigned int m_uiCount;
T* m_poData;
};
template<class T>
class SmartPointer
{
public:
SmartPointer();
SmartPointer(SmartData<T>& a_oSmartData);
SmartPointer(const SmartPointer& a_oSmartPointer);
~SmartPointer();
SmartPointer<T>& operator = (const SmartPointer<T>& a_oSmartPointer);
T operator *() const;
SmartData<T>* operator ->() const;
unsigned int GetCount() const;
private:
SmartData<T>* m_poSmartData;
};
#include "smartpointer.inl"
Inline file:
template<class T>
SmartData<T>::SmartData()
{
m_uiCount = 0;
m_poData = new T();
}
template<class T>
SmartData<T>::SmartData(const T& a_oData)
{
m_uiCount = 0;
m_poData = new T(a_oData);
}
template<class T>
SmartData<T>::~SmartData()
{
if (m_poData)
{
delete m_poData;
}
}
template<class T>
T SmartData<T>::operator * () const
{
return *m_poData;
}
template<class T>
void SmartData<T>::DecrementCount()
{
if (m_uiCount - 1 == 0 || m_uiCount == 0)
{
DeleteThis();
return;
}
--m_uiCount;
}
template<class T>
void SmartData<T>::DeleteThis()
{
if (m_poData)
{
delete m_poData;
m_poData = 0;
}
}
template<class T>
SmartPointer<T>::SmartPointer()
{
m_poSmartData = new SmartData<T>();
m_poSmartData->IncrementCount();
}
template<class T>
SmartPointer<T>::SmartPointer(SmartData<T>& a_oSmartData)
{
m_poSmartData = &a_oSmartData;
m_poSmartData->IncrementCount();
}
template<class T>
SmartPointer<T>::SmartPointer(const SmartPointer& a_oSmartPointer)
{
m_poSmartData = a_oSmartPointer.a_oSmartData;
m_poSmartData->IncrementCount();
}
template<class T>
SmartPointer<T>::~SmartPointer()
{
m_poSmartData->DecrementCount();
m_poSmartData = 0;
}
template<class T>
SmartPointer<T>& SmartPointer<T>::operator = (const SmartPointer<T>& a_oSmartPointer)
{
m_poSmartData = a_oSmartPointer.m_poSmartData;
m_poSmartData->IncrementCount();
}
template<class T>
T SmartPointer<T>::operator *() const
{
return *m_poSmartData->m_poData;
}
template<class T>
SmartData<T>* SmartPointer<T>::operator ->() const
{
return m_poSmartData;
}
template<class T>
unsigned int SmartPointer<T>::GetCount() const
{
return m_poSmartData->m_uiCount;
}
main.cpp
void SomeFunction1(SmartData<Test>& a_SmartData)
{
SmartPointer<Test> oSmartPointer2(a_SmartData);
}
void main()
{
SmartData<int> oSmartData1(5);
if (1)
{
SmartPointer<int> oSmartPointer1(oSmartData1);
int iTemp1 = oSmartPointer1->GetCount();
int iTemp2 = *oSmartPointer1;
int iTemp3 = *oSmartData1;
}
if (1)
{
SmartData<int> oSmartData2(5);
}
SmartData<Test> oSmartData3;
(*oSmartData3).m_iTest1 = 5; //Does not work
if (1)
{
SmartData<Test> oSmartData4(oSmartData3);
SomeFunction1(oSmartData3);
//oSmartData4 still exits
}
}
Everything works fine, the data is cleaned up after itself and I get no leaks... except for one line:
(*oSmartData3).m_iTest1 = 5;
I'm compiling with visual studio, and when I place the "." after "(*oSmartData3)"... "m_iTest1" comes up correctly. Except I get an error:
error C2106: '=' : left operand must be l-value
I'm not sure why this doesn't work or what to change so it does work.
Look closer at the declaration of operator*() in SmartData:
T operator * () const;
This means that this operator is returning an object of type T, which is a copy of m_poSmartData->m_poData. It is a temporary object in this context:
(*oSmartData3).m_iTest1 = 5; //Does not work
Of course, you cannot assign a value to a temporary object, because it is not an l-value. Read more about what l-values and r-values are here: http://publib.boulder.ibm.com/infocenter/comphelp/v7v91/index.jsp?topic=%2Fcom.ibm.vacpp7a.doc%2Flanguage%2Fref%2Fclrc05lvalue.htm
I would suggest that you return a reference to m_poSmartData->m_poData
in operator*() (if I'm understanding correctly what you are trying to do).
Your T operator *() const is returning a temporary object (i.e. a copy), which is not an l-value (cannot be assigned to). Return a reference instead:
T& operator *() const;
Does this work:
oSmartData3.m_iTest1 = 5;