Call destructor via void pointer with templates - c++

I wrote a class to contain my objects in it.
The code is:
class objectPool
{
private:
struct itemType_{uint count; void* object;};
std::multimap< std::string, itemType_ > pool_;
public:
template<class T>
bool addItem(std::string key, T*& object)
{
std::multimap< std::string, itemType_ >::iterator
i = pool_.find(key);
if(i != pool_.end())
{
object = (T*)(*i).second.object;
(*i).second.count++;
return true;
}
i = pool_.insert(std::pair<std::string,itemType_>(key, (itemType_){1, NULL}));
object = (T*)(*i).second.object;
return false;
}
template<class T>
bool removeItem(std::string key)
{
std::multimap< std::string, itemType_ >::iterator
i = pool_.find(key);
if(i != pool_.end())
{
if((*i).second.count == 1)
{
//important to call the appropriate destructor
delete ((T*)(*i).second.object);
pool_.erase(i);
}
else
(*i).second.count--;
return true;
}
return false;
}
};
And the test code:
#include "objectPool.h"
class testClass
{
public:
~testClass()
{
// I should get here at least once
std::cout << "I am deleted teehee";
}
};
testClass* test;
objectPool myPool;
int main () {
if(!myPool.addItem<testClass>("baba", test))
{
test = new testClass;
}
myPool.removeItem<testClass>("baba");
}
For some reason my test object's destructor does not want to be invoked.
First questcha: Why? Where I am wrong?
The sec.: Should I use auto_ptr instead? (Although I want to avoid using templates...)
The third.: Is there a better(-looking) solution? (with or without using templates)
The fourth.: Is there a way to invoke constructor via void pointer without templates (or without knowing the original type)?
Thanks ahead! :D
And sorry for my terrific english (not my native language, although...)

You correctly store a NULL into your T* reference, but that is a reference to the local variable. When you later update that local by calling new, that has no effect on the item stored in the pool.
The easier way to fix this would be to just create the object inside the addItem function using new T.
As for your other question, a way to call the destructor without knowing the original type, there is no way to do that. But there is a trick you can use with templates. You can create a template function like the one below, and then pass around a function pointer to it.
template<typename T>
void deleter(void *ptr)
{
delete static_cast<T*>(ptr);
}
deleter as a simple type which you can typedef and pass around pointers:
typedef void (*deleter_func)(void *);
To get a pointer to it, just do something like this in your addItem function:
deleter_func myDeleter = &deleter<T>;
Then later:
myDeleter(somePtr);
You don't need to know the type of somePtr at the time of deletion, just need to keep a pointer to the deleter. You can also use this method with shared_ptr, which can use a deleter argument.

My guess is it's going wrong because you're inserting {1, NULL} into the map. Changing the value of test in the main function doesn't affect the content of the map.

For some reason my test object's destructor does not want to be invoked. First questcha: Why? Where I am wrong?
Your test code is wrong. You add some uninitialized pointer into the structure. Try this:
int main () {
test = new testClass();
if(!myPool.addItem<testClass>("baba", test))
{
// Duplicate, I presume...
}
myPool.removeItem<testClass>("baba");
}
The sec.: Should I use auto_ptr instead?
std::auto_ptr is designed for dynamically allocated local variables, it is not designed for container implementation. Your current design limits that, anyways. However, I would write the test code as
int main () {
std::auto_ptr<testClass> test(new testClass());
if(myPool.addItem<testClass>("baba", test.get()))
{
test.release();
}
myPool.removeItem<testClass>("baba");
}
The third.: Is there a better(-looking) solution?
Yes, there is some type-safe heterogenous container in boost. I would look at that.
The fourth.: Is there a way to invoke constructor via void pointer without templates (or without knowing the original type)?
You can use the placement new operator if you want to construct an object in pre-allocated memory. std::vector does this a lot. However, there is no way to construct an object without knowing the type. How would you specify what type's constructor to invoke? If you need this, you'll probably want to look into the factory method pattern.

Related

Correct usage of unique_ptr in class member

I am trying to really move from c++98 to c++11 and newer. I have wrapped my head over most of the new stuff but I am still not sure about the correct usage of unique_ptr.
Consider the example below, where class A has a unique_ptr member (I would have used raw pointer before!). This member variable should be assigned, when user needs, by calling a function somewhere else (not part of the class). Is this the correct usage? If not, what is the best alternative?
class A {
private:
unique_ptr<MyType> mt;
public:
void initStuff() {
mt.reset(std::move(StaticFuncSomewhereElese::generateMyType()));
}
};
MyType* StaticFuncSomewhereElese::generateMyType() {
MyType* temp = new MyType(...);
//do stuff to temp (read file or something...)
return temp;
}
Your code works fine (although the redundant* move can be omitted) but it would be better to construct the unique_ptr as early as possible:
class A {
private:
std::unique_ptr<MyType> mt;
public:
void initStuff() {
mt = StaticFuncSomewhereElese::generateMyType();
}
};
std::unique_ptr<MyType> StaticFuncSomewhereElese::generateMyType() {
auto temp = std::make_unique<MyType>(…);
// `make_unique` is C++14 (although trivially implementable in C++11).
// Here's an alternative without `make_unique`:
// std::unique_ptr<MyType> temp(new MyType(…));
//do stuff to temp (read file or something...)
return temp;
}
This way it is clear that the return value of generateMyType must be deleted by the caller, and there's less possibility for memory leaks (e.g. if generateMyType returns early).
* The move is redundant because:
Raw pointers can't be moved.
The result of the generateMyType() expression is already an rvalue anyways.
Is this the correct usage?
Besides std::move being redundant, yes this is correct. It is redundant because a) Bare pointers are copied, whether they are lvalues or rvalues and b) The function doesn't return a reference, so the return value is already an rvalue so there is no need to convert.
But there is room for improvement. In particular, I recommend to return a unique pointer from the factory function:
std::unique_ptr<MyType> StaticFuncSomewhereElese::generateMyType()
This prevents temp from leaking if the initialization throws an exception, and makes it much harder for the user of the factory to accidentally leak the returned pointer.
Why not make it a generic template factory?
In header.
template <typename T>
std::unique_ptr<T> generateMyType();
classss A {
private:
std::unique_ptr<MyType> mt;
std::unique_ptr<MyOtherType> mot;
public:
void initStuff() {
mt = generateMyType<MyType>();
mot = generateMyType<MyOtherType>();
}
};
And in the source file
template <typename T>
std::unique_ptr<T> generateMyType()
{
auto temp = std::make_unique<T>();
return temp;
}

C++ force dynamic allocation with unique_ptr?

I've found out that unique_ptr can point to an already existing object.
For example, I can do this :
class Foo {
public:
Foo(int nb) : nb_(nb) {}
private:
int nb_;
};
int main() {
Foo f1(2);
Foo* ptr1(&f1);
unique_ptr<Foo> s_ptr1(&f1);
return 0;
}
My question is :
If I create a class with unique_ptr< Bar > as data members (where Bar is a class where the copy constructor was deleted) and a constructor that takes pointers as argument, can I prevent the user from passing an already existing object/variable as an argument (in that constructor) (i.e. force him to use the new keyword) ?
Because if he does, I won't be able to guarantee a valide state of my class objects (the user could still modify data members with their address from outside of the class) .. and I can't copy the content of Bar to another memory area.
Example :
class Bar {
public:
Bar(/* arguments */) { /* data members allocation */ }
Bar(Bar const& b) = delete;
/* Other member functions */
private:
/* data members */
};
class Bar_Ptr {
public:
Bar_Ptr(Bar* ptr) {
if (ptr != nullptr) { ptr_ = unique_ptr<Bar> (ptr); }
} /* The user can still pass the address of an already existing Bar ... */
/* Other member functions */
private:
unique_ptr<Bar> ptr_;
};
You can't prevent programmers from doing stupid things. Both std::unique_ptr and std::shared_ptr contain the option to create an instance with an existing ptr. I've even seen cases where a custom deleter is passed in order to prevent deletion. (Shared ptr is more elegant for those cases)
So if you have a pointer, you have to know the ownership of it. This is why I prefer to use std::unique_ptr, std::shared_ptr and std::weak_ptr for the 'owning' pointers, while the raw pointers represent non-owning pointers. If you propagate this to the location where the object is created, most static analyzers can tell you that you have made a mistake.
Therefore, I would rewrite the class Bar_ptr to something like:
class Bar_ptr {
public:
explicit Bar_ptr(std::unique_ptr<Bar> &&bar)
: ptr(std::move(bar)) {}
// ...
}
With this, the API of your class enforces the ownership transfer and it is up to the caller to provide a valid unique_ptr. In other words, you shouldn't worry about passing a pointer which isn't allocated.
No one prevents the caller from writing:
Bar bar{};
Bar_ptr barPtr{std::unique_ptr<Bar>{&bar}};
Though if you have a decent static analyzer or even just a code review I would expect this code from being rejected.
No you can't. You can't stop people from doing stupid stuff. Declare a templated function that returns a new object based on the templated parameter.
I've seen something similar before.
The trick is that you create a function (let's call it make_unique) that takes the object (not pointer, the object, so maybe with an implicit constructor, it can "take" the class constructor arguments) and this function will create and return the unique_ptr. Something like this:
template <class T> std::unique_ptr<T> make_unique(T b);
By the way, you can recommend people to use this function, but no one will force them doing what you recommend...
You cannot stop people from doing the wrong thing. But you can encourage them to do the right thing. Or at least, if they do the wrong thing, make it more obvious.
For example, with Bar, don't let the constructor take naked pointers. Make it take unique_ptrs, either by value or by &&. That way, you force the caller to create those unique_ptrs. You're just moving them into your member variables.
That way, if the caller does the wrong thing, the error is in the caller's code, not yours.

Is it possible to choose between constructors in main without writing a copy-constructor?

Real example is obviously much longer, but this sums up my problem:
class Object
{
int mInt1,mInt2;
Object::Object();
Object::Object(int param1);
Object::Object(int param1, int param2);
};
Object::Object(){}
Object::Object(int param1):mInt1(param1){}
Object::Object(int param1, int param2):mInt1(param1),mInt1(param2){}
Then in main:
if (type1){
Object instance(param1);
}
else{
Object instance(param1,param2);
}
// do stuff with instance
Whoops! That won't work, instance is out of scope for the program that follows.
Object instance;
if (type1){
instance = Object(param1);
}
else{
instance = Object(param1,param2);
}
// do stuff with instance
But now I run in to trouble because I didn't have a copy constructor defined. I'd really rather not write a copy-constructor because my actual class has dozens of members, many of which are non-basic types and might require even more work to copy.
Specifically, I am getting
main.cpp: error: use of deleted function ‘Object& Object::operator=(Object&&)’
instance = Object(param1);
^
note: ‘Object& Object::operator=(Object&&)’ is implicitly deleted because the default definition would be ill-formed:
The universal way to deal with non-copyable objects is to throw it into a unique_ptr (or auto_ptr, depending on your compiler).
std::unique_ptr<Object> instance;
if (type1) {
instance.reset(new Object(i));
}
else {
instance.reset(new Object(i, j));
}
Using raw pointers here really isn't safe because once you start having to deal with exceptions or any interesting code paths it becomes a chore to worry about leaks. Trust me, in 100% of cases, you will have less work and lines of code to deal with if you just drop it in a unique_ptr.
An optimal solution would be to redesign Object's constructors, because circumventing non-copyability may leave the object in an illegal state. In general, you want to preserve non-copyability if the compiler thinks it's necessary. We don't have the details here to flesh out such a solution however.
If you do not want dynamically allocation then you can use an Initialize function:
class Object
{
int mInt1,mInt2;
Object::Object();
Object::Initialize();
Object::Initialize(int param1);
Object::Initialize(int param1, int param2);
};
Object::Object(){Initialize();} //call the empty Initialize for nice coding...:)
Object::Initialize(){ }
Object::Initialize(int param1){ mInt1(param1); }
Object::Initialize(int param1, int param2){ mInt1(param1);mInt1(param2);}
Then you can use initialize to select the type.
Object instance;
if (type1){
instance.Initialize(param1);
}
else{
instance.Initialize(param1,param2);
}
Here is a low-level(ish) solution which does what you want. I will leave it up to you to decide whether it's a good idea to use it:
#include <type_traits>
template <class T>
class MultiInitialiser
{
T *object;
std::aligned_storage<T> storage;
public:
MultiInitialiser() : object(nullptr)
{}
template <class... Arg>
void initialise(Arg &&... arg)
{
if (object)
throw "Double init error";
object = new (&storage) T(std::forward<Arg>(arg)...);
}
operator T& ()
{ return *object; }
operator const T& () const
{ return *object; }
~MultiInitialiser()
{
if (object)
object->~T();
}
};
Copy/move operations for the above are left as an excercise for the reader ;-)
The class would then be used like this:
MultiInitialiser<Object> instance;
if (type1){
instance.initialise(param1);
}
else{
instance.initialise(param1,param2);
}
Apart from the cast to T, you could also give the class operator* and operator-> returning the contained object, similar to what boost::optional does.
There are a couple of options that let you do this while retaining automatic storage, and which one you should use depends on the semantics of the type Object.
The POD
If you have a type like the one given in the question, you might choose to reduce it to a POD type; basically, remove all of the user-provided constructors and give everything the same access specifier:
struct Object {
int mInt1, mInt2;
};
Then, your initialization pattern might look like this (using placement new):
Object o; // Default-initialized, a no-op
if (condition)
new (&o) Object {i};
else
new (&o) Object {i, j};
General Types
Generally speaking, your typical value-semantic type will work perfectly fine if you default-initialize and then assign, thanks to move semantics:
std::vector <foo> v;
if (condition)
v = std::vector <foo> (42);
else
v = std::vector <foo> {bar, baz, quux};
Often, though, you'll still be doing work in the default constructor, because certain types' default-constructed objects (e.g., std::vector) have well-defined state. If you want to avoid this work for an arbitrary predefined type, you might want to use std::optional (as of this writing not actually yet standard):
std::optional <big_but_flat> b;
if (condition)
b.emplace (i);
else
b.emplace (i, j);
Without std::optional
You might object that std::optional has too much overhead associated with it, and I'll leave it to you and your measurements to decide whether that's the case. At any rate, we can get our behaviour without worrying about that overhead— but may the nasal demons have mercy if you don't actually perform your initialization. We'll use a union to get what we want:
// At function scope
union store_v {
std::vector <int> v;
store_v () {}
~store_v () { v.~vector <int> (); }
} sv;
if (condition)
new (&sv.v) std::vector <int> (42);
else
new (&sv.v) std::vector <int> {49, 343, 2401};
This may be improved. For example, we can make the storage a template:
template <typename T>
union store {
T t;
store () {}
~store () { t.~T (); }
};
// At function scope
store <std::vector <int>> sv;
if (condition)
new (&sv.t) std::vector <int> (42);
else
new (&sv.t) std::vector <int> {49, 343, 2401};
We can give ourselves a reference:
template <typename T>
union store {
T t;
store () {}
~store () { t.~T (); }
};
// At function scope
store <std::vector <int>> sv;
auto&& v = sv.t; // Deduce const, for what that's worth
if (condition)
new (&v) std::vector <int> (42);
else
new (&v) std::vector <int> {49, 343, 2401};
And with a little attention to detail to avoid name collisions and handle C++'s… interesting declaration syntax, we could even define a couple of macros to clean the code up (implementation left as an exercise to the reader):
template <typename T>
union store {
T t;
store () {}
~store () { t.~T (); }
};
// At function scope
DECL_UNINIT (std::vector <int>, v);
if (condition)
INIT (v, (42));
else
INIT (v, {49, 343, 2401});
You can use a pointer to your object and instantiate it by new operator:
Object * instance;
if (type1){
instance = new Object(param1);
}
else{
instance = new Object(param1,param2);
}
You're using something that is called copy elision.
This states that the compiler MAY optimize the code and avoid a copy constructor in such a case.
But it doesn't have to, and may use a copy constructor anyway.
The right way (without being subjected to the whims of the compiler) would be to use a pointer:
Object* instance;
if (type1){
instance = new Object(param1);
}
else{
instance = new Object(param1,param2);
}
In your version of one-parameter constructor, the mInt2 member is just ignored (isn't ever initialized), so I assume that you don't do any computation with that member if type1 is false (though I don't know how you're doing it without storing type1).
So, why don't just change the dessign? Make te constructor take int param1, int param2 and type1 as parameters and choose internally how to build himself:
class Object
{
int mInt1,mInt2;
Object::Object() :
mInt1(0), // don't forget to initialize your values!
mInt2(0)
{}
// Object::Object(int param1); no more 1-parameter ctor.
Object::Object(int param1, int param2, type type1) :
mInt1(param1),
mInt2(type1 ? param2 : 0) // assuming that 0 isn't a valid value for mInt2
{}
};
Then in main:
Object instance(param1, param2, type1);
// do stuff with instance
I guess that it looks a little neater.
You could write a move assignment. Depending what your data members look like, you may get away with memcopying some or all of them, cf. Move constructor with memcpy.
That said, I assume that either you need a full set of constructors/destructors, including copy and assignment; that will always be necessary if you want to have it in containers, assign it etc. Or else the class doesn't need any of that and you just initialize the needed parts of it depending on the situation, and when you are done, you de-initialize manually.
I think I found a way to do it without requiring allocating the object on the heap, using a lambda.
Basically, the idea is to separate the construction from the usage. (the following assume that you fixed the difinition of Object so that it compiles)
auto work = []( Object& object ){
// here do the work on the object
};
// now create the object and apply the work in the process:
if (type1){
Object instance(param1);
work( instance );
}
else{
Object instance(param1,param2);
work( instance );
}
Here no copy was involved but the same code is still applied whatever the wy the object was constructed, and without having to declare an external function (as a lambda is a local function).
From the memory point of view, there will always be only one instance object so the stack memory allocated will always be the same size whatever the path.
Obviously, this don't work if the instance have to get out of the scope of the whole function. If it's the case, then you really need to allocate it on the heap using a smart pointer preferably.

Managing C type lifecycle using boost's shared_ptr?

I have a question similar to How to manage object life time using Boost library smart pointers? but, in my case, the "object" isn't a C++ object at all, but an opaque type returned/passed out from a C API. The type does not have pointer semantics, i.e., there is no dereferencing; it is, however, passed as an argument to other functions in the C API. The type also has a definitive close API which must be called in order to clean up internal resources.
So, I have a C API that's something along the lines of
opaque_legacy_type_t x;
XXopen(..., &x); // allocates/opens resource and fills out 'x' to be used later
XXdoSomethingWithResource(x, ...); // do something with resources related to 'x'
...more actions...
XXclose(x); // closes and cleans up resources related to 'x'
For various reasons, in my C++ code I would like to manage "instances" of opaque_legacy_type_t much like I would manage heap-allocated object instances, i.e. with similar sharing semantics as boost::shared_ptr<>. It seems that shared_ptr offers enough that I can manage calling XXclose by doing this:
opaque_legacy_type_t x;
XXopen(..., &x);
boost::shared_ptr<opaque_legacy_type_t> managed(x, XXclose);
But, since opaque_legacy_type_t doesn't have pointer semantics, the usage of managed is a bit clumsy.
What I'd like to do is have something like a managed_type that is similar to shared_ptr, and am looking for ideas that don't require me to write it all.
EDIT: I corrected my original screw-up in the example. The legacy API takes the opaque type by value rather than by pointer.
Since all of the legacy API take a pointer to the opaque type, you could use shared pointers directly. The key is for you to not declare the original structure on the stack, but rather allocate it via new:
int main () {
std::shared_ptr<opaque_legacy_type_t> x(new opaque_legacy_type_t,
[](opaqeue_legacy_type_t* p) { XXClose(p); delete p; });
XXopen(..., x.get());
XXdoSomethingWithResource(x.get(), ...);
}
EDIT: If some API take the opaque type by value instead of pointer, then pass the dereferenced pointer.
int main () {
std::shared_ptr<opaque_legacy_type_t> x(new opaque_legacy_type_t,
[](opaqeue_legacy_type_t* p) { XXClose(*p); delete p; });
XXopen(..., x.get());
XXdoSomethingWithResource(*x, ...);
}
You could use boost smart pointers together with the pimpl idom:
class shared_opaque_legacy_type_t {
struct impl {
opaque_legacy_type_t t;
impl(...) { XXOpen(..., t); }
~impl(...) { XXClose(t); }
}
boost::shared_ptr<impl> _impl;
public:
shared_opaque_lagacy_type_t(...) : _impl(new impl(...)) {}
opaque_legacy_type_t* get() {
return _impl->t;
}
};
shared_opaque_legacy_type_t x(...);
XXdoSomethingWithResource(x.get(), ...);
The drawback is that you could still call XXclose(x.get()) and invalidate your object.
UPDATE: Fixed it. :-)
You could write a wrapper to use with boost that will call the open() in the ctor and the close() in the dtor.
I voted for Rob's answer that just uses a shared_ptr with no wrapper, but if you really want to avoid dynamic allocation here's a simple little example of how to do that.
It's a template that directly holds the handle and does no allocation. You pass the constructor a functor that creates an object of the opaque type, and a deleter to call when the type needs to be destroyed. It's movable and non-copyable so now shared reference count is needed. It implements implicit conversion operators so you can use it where you'd use a value of the held type.
template<typename T,typename D>
class opaque_type_handle {
T handle;
D deleter;
bool needs_delete;
public:
template<typename F>
opaque_type_handle(F f,D d) : handle(f()), deleter(d), needs_delete(true) {}
opaque_type_handle(opaque_type_handle const &) = delete;
opaque_type_handle &operator=(opaque_type_handle const &) = delete;
opaque_type_handle(opaque_type_handle &&rhs) : handle(rhs.handle),deleter(rhs.deleter),needs_delete(true) {
rhs.needs_delete = false;
}
opaque_type_handle &operator=(opaque_type_handle &&rhs) {
handle = rhs.handle;
deleter = rhs.deleter;
needs_delete = true;
rhs.needs_delete = false;
returh *this;
}
~opaque_type_handle() {
if(needs_delete) {
deleter(handle);
}
}
operator T&() { return handle; }
operator T() const { return handle; }
};
Use it like so:
// wrap up the code for creating an opaque_legacy_type_t handle
typedef opaque_type_handle<opaque_legacy_type_t,decltype(&XXclose)> legacy_handle;
legacy_handle make_legacy_handle(...) {
return legacy_handle(
[](){
opaque_legacy_type_t tmp;
XXopen(..., &tmp);
return tmp;
},
&XXclose
);
}
legacy_handle x = make_legacy_handle(...);
XXdoSomethingWithResource(x,...);

Copy data from a pointer or chain of pointers (Object pointer, templates)

How the push_back of stl::vector is implemented so it can make copy of any datatype .. may be pointer, double pointer and so on ...
I'm implementing a template class having a function push_back almost similar to vector. Within this method a copy of argument should be inserted in internal allocated memory.
In case the argument is a pointer or a chain of pointers (an object pointer); the copy should be made of actual data pointed. [updated as per comment]
Can you pls tell how to create copy from pointer. so that if i delete the pointer in caller still the copy exists in my template class?
Code base is as follows:
template<typename T>
class Vector
{
public:
void push_back(const T& val_in)
{
T a (val_in); // It copies pointer, NOT data.
m_pData[SIZE++] = a;
}
}
Caller:
// Initialize my custom Vector class.
Vector<MyClass*> v(3);
MyClass* a = new MyClass();
a->a = 0;
a->b = .5;
// push MyClass object pointer
// now push_back method should create a copy of data
// pointed by 'a' and insert it to internal allocated memory.
// 'a' can be a chain of pointers also.
// how to achieve this functionality?
v.push_back(a);
delete a;
I can simply use STL vector to accomplish the tasks but for experiment purposes i'm writing a template class which does exactly the same.
Thanks.
if you have polymorphic object ( the pointed object may be more specialized than the variable ), I suggest you creating a virtual method called clone() that allocate a new pointer with a copy of your object:
Base* A::clone() {
A* toReturn = new A();
//copy stuff
return toReturn;
}
If you can't modify your Base class, you can use RTTI, but I will not approach this solution in this answer. ( If you want more details in this solution, please make a question regarding polymorphic cloning with RTTI).
If you have not a polymorphic object, you may allocate a new object by calling the copy constructor.
void YourVector::push_back(Base* obj) {
Base* copy = new Base(obj);
}
But it smells that what you are really needing is shared_ptr, avaliable in <tr1/memory> ( or <memory> if you use C++0x ).
Update based on comments
You may also have a two template parameters list:
template <typename T>
struct CopyConstructorCloner {
T* operator()(const T& t) {
return new T(t);
}
}
template <typename T, typename CLONER=CopyConstructorCloner<T> >
class MyList {
CLONER cloneObj;
public:
// ...
void push_back(const T& t) {
T* newElement = cloneObj(t);
// save newElemenet somewhere, dont forget to delete it later
}
}
With this approach it is possible to define new cloning politics for things like pointers.
Still, I recommend you to use shared_ptrs.
I think for this kind of problems it is better to use smart pointers ex: boost::shared_ptr or any other equivalent implementation.
There is no need to call new for the given datatype T. The push_back implementation should (must) call the copy-constructor or the assignment operator. The memory should have been allocated to hold those elemnets that are being pushed. The intial memory allocation should not call CTOR of type T. Something like:
T* pArray;
pArray = (T*) new BYTE[sizeof(T) * INITIAL_SIZE);
And then just put new object into pArray, calling the assignment operator.
One solution is to make a copy construction:
MyClass *p = new MyClass();
MyVector<MyClass*> v;
v.push_back(new MyClass(*p));
Update: From you updated question, you can definitely override push_back
template<typename T>
class MyVector {
public:
void push_back (T obj); // general push_back
template<typename TYPE> // T can already be a pointer, so declare TYPE again
void push_back (TYPE *pFrom)
{
TYPE *pNew = new TYPE(*pFrom);
// use pNew in your logic...
}
};
Something like this:
template<typename T>
class MyVector
{
T* data; // Pointer to internal memory
size_t count; // Number of items of T stored in data
size_t allocated; // Total space that is available in data
// (available space is => allocated - count)
void push_back(std::auto_ptr<T> item) // Use auto pointer to indicate transfer of ownership
/*void push_back(T* item) The dangerous version of the interface */
{
if ((allocated - count) == 0)
{ reallocateSomeMemory();
}
T* dest = &data[count]; // location to store item
new (dest) T(*item); // Use placement new and copy constructor.
++count;
}
// All the other stuff you will need.
};
Edit based on comments:
To call it you need to do this:
MyVector<Plop> data;
std::auto_ptr<Plop> item(new Plop()); // ALWAYS put dynamically allocated objects
// into a smart pointer. Not doing this is bad
// practice.
data.push_back(item);
I use auto_ptr because RAW pointers are bad (ie in real C++ code (unlike C) you rarely see pointers, they are hidden inside smart pointers).