use iterator ptr to update vector of unique_ptr - c++

Code as follows:
#include "MyObject.h"
#include <vector>
#include <memory>
class MyCollection {
private:
std::vector<std::unique_ptr<MyObject*>> collection;
public:
MyCollection();
virtual ~MyCollection();
int insert(MyObject* newValue);
};
int MyCollection::insert(MyObject* newValue) {
if (collection.empty()) {
collection.push_back(move(make_unique<MyObject*>(newValue)));
return 0;
}
int index = collection.size()-1;
collection.resize(collection.size()+1);
vector<unique_ptr<MyObject*>>::reverse_iterator pos = collection.rbegin();
for ( ; (index >= 0) && (pos+1) != collection.rend() && stringToUpper((*(pos+1)->get())->getObjectName()) > stringToUpper(newValue->getObjectName()); ++pos) {
pos = (pos+1);
index--;
}
pos = ?newValue; // How do I do this?
//pos->reset(move(make_unique<MyObject*>(newValue)));
return index+1;
}
make_unique() implementation taken from http://scrupulousabstractions.tumblr.com/post/37576903218/cpp11style-no-new-delete
My question is there a way to do what I'm attempting with the assignment to the reverse_iterator (pos = newValue)? One of my pitiful attempts is shown in the commented code.
Thanks!

Firstly, as others have pointed out, you want a vector<unique_ptr<MyObject>> not vector<unique_ptr<MyObject*>>. It is fine to have a unique_ptr containing an abstract class (make sure the base class has a virtual destructor). You can implicitly cast from a unique_ptr containing a derived class.
Ideally I think MyCollection::insert should take a unique_ptr not a raw pointer so that the calling code creates objects using make_unique in the first place but let's leave it like it is for now.
I think you have a bit of confusion with make_unique. make_unique is designed to create an object and wrap it in a unique_ptr in one go, safely. Your MyCollection::insert doesn't really need to use make_unique because the object is already created. unique_ptr has a constructor that takes a raw pointer so you can create one directly from the raw pointer.
You can then push the unique_ptr onto the collection or replace unique_ptrs in the collection with new unique_ptrs fine:
class MyObject {
public:
virtual ~MyObject() = 0
};
MyObject::~MyObject() {}
class SimSolverObject : public MyObject {
};
class MyCollection {
private:
std::vector<std::unique_ptr<MyObject>> collection;
public:
void insert(MyObject* newValue);
};
void MyCollection::insert(MyObject* newValue) {
//...
// if we want to add to the collection
collection.push_back(std::unique_ptr<MyObject>(newValue));
// if we want to replace at iterator pos in collection
*pos = std::unique_ptr<MyObject>(newValue);
}
// calling code
MyCollection mc;
MyObject* newValue = new SimSolverObject();
mc.insert(newValue)
If you do decide to change MyCollection::insert to take a unique_ptr it would look something like this:
void MyCollection::insert(std::unique_ptr<MyObject> newValue) {
//...
// if we want to add to the collection
collection.push_back(std::move(newValue));
// if we want to replace at pos
*pos = std::move(newValue);
}
Edit: Your for loop looks a bit suspicious. I am not quite sure what you are trying to do but are you sure you want to increment the iterator twice? Once in the body of the for and once in the loop expression? I suspect the iterator is skipping over your condition and going out of bounds of the vector. When it hits the index condition you may be left with an invalid iterator.

Related

Reusable std::shared_ptr

Is it possible to make std::shared_ptr not to delete an object, but move it to a list?
#include <memory>
#include <list>
struct QObject { double socialDistance; };
int main()
{
std::list<QObject *> free_objects;
std::list<QObject *> used_objects;
QObject* p_object = new QObject{10};
free_objects.push_back(p_object);
{
std::shared_ptr<QObject> p(p_object);
}
//At this point p_object is moved from free_objects to used_objects,
//so I reuse the object later.
return 0;
}
If yes, is it possible to reuse not only the objects but also the control block to avoid memory reallocation?
Is it possible to make std::shared_ptr not to delete an object, but move it to a list?
You might use custom deleter for that:
std::shared_ptr<QObject> p(p_object, [&](QObject* p){
used_objects.push_back(p);
auto it = std::find(free_objects.begin(), free_objects.end(), p);
if (it != free_objects.end()) free_objects.erase(it);
});
Demo

wondering if I can use stl smart pointers for this

I currently have a c++ class as follows:
template<class T>
class MyQueue {
T** m_pBuffer;
unsigned int m_uSize;
unsigned int m_uPendingCount;
unsigned int m_uAvailableIdx;
unsigned int m_uPendingndex;
public:
MyQueue(): m_pBuffer(NULL), m_uSize(0), m_uPendingCount(0), m_uAvailableIdx(0),
m_uPendingndex(0)
{
}
~MyQueue()
{
delete[] m_pBuffer;
}
bool Initialize(T *pItems, unsigned int uSize)
{
m_uSize = uSize;
m_uPendingCount = 0;
m_uAvailableIdx = 0;
m_uPendingndex = 0;
m_pBuffer = new T *[m_uSize];
for (unsigned int i = 0; i < m_uSize; i++)
{
m_pBuffer[i] = &pItems[i];
}
return true;
}
};
So, I have this pointer to arrays m_pBuffer object and I was wondering if it is possible to replace this way of doing things with the c++ smart pointer perhaps? I know I can do things like:
std::unique_ptr<T> buffer(new T[size]);
Is using a vector of smart pointers the way to go? Is this recommended and safe?
[EDIT]
Based on the answers and the comments, I have tried to make a thread-safe buffer array. Here it is. Please comment.
#ifndef __BUFFER_ARRAY_H__
#define __BUFFER_ARRAY_H__
#include <memory>
#include <vector>
#include <mutex>
#include <thread>
#include "macros.h"
template<class T>
class BufferArray
{
public:
class BufferArray()
:num_pending_items(0), pending_index(0), available_index(0)
{}
// This method is not thread-safe.
// Add an item to our buffer list
void add(T * buffer)
{
buffer_array.push_back(std::unique_ptr<T>(buffer));
}
// Returns a naked pointer to an available buffer. Should not be
// deleted by the caller.
T * get_available()
{
std::lock_guard<std::mutex> lock(buffer_array_mutex);
if (num_pending_items == buffer_array.size()) {
return NULL;
}
T * buffer = buffer_array[available_index].get();
// Update the indexes.
available_index = (available_index + 1) % buffer_array.size();
num_pending_items += 1;
return buffer;
}
T * get_pending()
{
std::lock_guard<std::mutex> lock(buffer_array_mutex);
if (num_pending_items == 0) {
return NULL;
}
T * buffer = buffer_array[pending_index].get();
pending_index = (pending_index + 1) % buffer_array.size();
num_pending_items -= 1;
}
private:
std::vector<std::unique_ptr<T> > buffer_array;
std::mutex buffer_array_mutex;
unsigned int num_pending_items;
unsigned int pending_index;
unsigned int available_index;
// No copy semantics
BufferArray(const BufferArray &) = delete;
void operator=(const BufferArray &) = delete;
};
#endif
Vector of smart pointers is good idea. It is safe enough inside your class - automatic memory deallocation is provided.
It is not thread-safe though, and it's not safe in regard of handling external memory given to you by simple pointers.
Note that you current implementation does not delete pItems memory in destructor, so if after refactoring you mimic this class, you should not use vector of smart pointers as they will delete memory referenced by their pointers.
On the other side you cannot garantee that noone outside will not deallocate memory for pItems supplied to your Initialize. IF you want to use vector of smart pointers, you should formulate contract for this function that clearly states that your class claims this memory etc. - and then you should rework outside code that calls your class to fit into new contract.
If you don't want to change memory handling, vector of simple pointers is the way to go. Nevertheless, this piece of code is so simple, that there is no real benefit of vector.
Note that overhead here is creation of smart pointer class for each buffer and creation of vector class. Reallocation of vector can take up more memory and happens without your direct control.
The code has two issues:
1) Violation of the rule of zero/three/five:
To fix that you do not need a smart pointer here. To represent a dynamic array with variable size use a std:vector<T*>. That allows you to drop m_pBuffer, m_uSize and the destructor, too.
2) Taking the addresses of elements of a possible local array
In Initialize you take the addresses of the elements of the array pItems passed as argument to the function. Hence the queue does not take ownership of the elements. It seems the queue is a utility class, which should not be copyable at all:
template<class T>
class MyQueue
{
std::vector<T*> m_buffer;
unsigned int m_uPendingCount;
unsigned int m_uAvailableIdx;
unsigned int m_uPendingndex;
public:
MyQueue(T *pItems, unsigned int uSize)
: m_buffer(uSize, nullptr), m_uPendingCount(0), m_uAvailableIdx(0), m_uPendingndex(0)
{
for (unsigned int i = 0; i < uSize; i++)
{
m_buffer[i] = &pItems[i];
}
}
private:
MyQueue(const MyQueue&); // no copy (C++11 use: = delete)
MyQueue& operator = (const MyQueue&); // no copy (C++11 use: = delete)
};
Note:
The red herring is the local array.
You may consider a smart pointer for that, but that is another question.

class with unique_ptr of vector to class

How to implement a class containing a unique_ptr to a vector containing elements of the same class to build kind of a hierarchical structure.
I had implemented the same example using normal pointer before. That had worked fine.
Now I am trying to adapt to c++11 using unique_ptr.
The line marked with the "works" comment seems to do what I expect. The same kind of statement used inside the copy construct seems to fail copying the actual contents of the vector into the new instance.
I am using Visual Studio 2013.
Background information:
I have stripped down the class. The iPOD is only representing a lot of other members also existing within the class.
The class is used as representation of single attributes of an HMI widget tree.
#include <string>
#include <memory>
#include <vector>
void func();
struct Attribute;
typedef std::vector<Attribute> AttributeVector;
struct Attribute
{
int m_iPOD;
//AttributeVector *m_kAttrVectorPtr; // Old version before unique_ptr did work...
std::unique_ptr<AttributeVector> m_kAttrVectorPtr; // New version using unique_ptr
/** Default constructor. */
Attribute()
: m_iPOD(-1), m_kAttrVectorPtr(nullptr)
{
}
/** Constructs an attribute. */
Attribute(int iPOD, std::unique_ptr<AttributeVector> kAttrs)
: m_iPOD(iPOD), m_kAttrVectorPtr(std::move(kAttrs))
{}
/** Copy constructor.
#param kSource Source instance.
*/
Attribute(const Attribute& kSource)
: m_iPOD(kSource.m_iPOD)
{
if(kSource.m_kAttrVectorPtr)
m_kAttrVectorPtr = std::unique_ptr<AttributeVector> (new AttributeVector(kSource.m_kAttrVectorPtr));
else
m_kAttrVectorPtr = nullptr;
}
/** Assignment operator.
#param kSource Source instance.
*/
Attribute& operator=(const Attribute& kSource)
{
m_iPOD = kSource.m_iPOD;
if(kSource.m_kAttrVectorPtr)
m_kAttrVectorPtr = std::unique_ptr<AttributeVector> (new AttributeVector(kSource.m_kAttrVectorPtr));
else
m_kAttrVectorPtr = nullptr;
return *this;
}
bool operator==(const Attribute& rkOther) const
{
return m_iPOD == rkOther.m_iPOD;
// Todo real compare m_kAttrVectorPtr == rkOther.m_kAttrVectorPtr;
}
bool operator!=(const Attribute& rkOther) const
{
return !operator==(rkOther);
}
};
int main()
{
AttributeVector kVector;
Attribute kAttr1;
kAttr1.m_iPOD = 101;
kAttr1.m_kAttrVectorPtr = nullptr;
Attribute kAttr2;
kAttr2.m_iPOD=102;
kAttr2.m_kAttrVectorPtr = nullptr;
kVector.push_back(kAttr1);
kVector.push_back(kAttr2);
Attribute kAttr;
kAttr.m_iPOD=100;
kAttr.m_kAttrVectorPtr = std::unique_ptr<AttributeVector> (new AttributeVector(kVector)); // Works result= kattr with a vector of 2 attributes
Attribute kAttrCopy(kAttr);// does not work. Only one entry within m_kAttrVectorPtr after copy instead of the 2 from above
Attribute kAttrAssign;
kAttrAssign = kAttr;// does not work. Only one entry within m_kAttrVectorPtr after copy instead of the 2 from above
return 0;
}
The idea of unique_ptr is to manage an object on the heap, i.e. to automatically delete it once the pointer goes out of scope. A vector does the same with its contents, so allocating a vector on the heap is just a waste of resources (time and memory). This means that already your previous design which allocated a vector was flawed. Instead of
struct A {
vector<A> *pvec;
A() : pvec(new vector<A>) {}
~A() { delete pvec; }
};
(which you are attempting to improve with unique_ptr), simply use
struct A {
vector<A> vec; // requires 24 bytes on 64bit machines
// auto generated constructor and destructor
};
Alternatively, if the number of objects hold in the vector are known at the start, you could use a unique_ptr:
struct A {
unique_ptr<A[]> vec; // requires 8 bytes on 64bit machines
A(size_t n)
: vec(new A[n]) {}
};
Replace new AttributeVector(kSource.m_kAttrVectorPtr) with new AttributeVector(*kSource.m_kAttrVectorPtr).
You can't construct a vector with any pointer, but with the value itself. (*)

Using shared pointers with memory allocated in another function

I have some legacy-era code at work that takes in a double-pointer and allocates memory to it. A shortened example of it would look something like this:
struct LegacyObj
{
int a;
double b;
};
void LegacyAllocator(LegacyObj** ppObj)
{
*ppObj = (LegacyObj*)malloc(sizeof(LegacyObj));
}
void LegacyDeleter(LegacyObj** ppObj)
{
free(*ppObj);
}
The actual LegacyAllocator function is ~100 lines and mixes reading from files with creating a linked list of LegacyObj pointers, and isn't something I'd be able to get away with rewriting right now. I would like, however, to make the use of this function a bit safer, avoiding any memory leaks that may occur from exceptions &tc. The first solution I came up with was to wrap it up in a class and handle calling the legacy functions in the ctor/dtor.
class RAIIWrapper
{
public:
RAIIWrapper()
:obj{nullptr}
{
::LegacyAllocator(&obj);
}
RAIIWrapper(RAIIWrapper&& that)
: obj{ that.obj}
{
that.obj = nullptr;
}
RAIIWrapper& operator=(RAIIWrapper&& that)
{
RAIIWrapper copy{std::move(that)};
std::swap(obj, copy.obj);
return *this;
}
~RAIIWrapper ()
{
::LegacyDeleter(&obj);
}
private:
LegacyObj* obj;
};
But I'm curious - is there a way to do this using std::shared_ptr or std::unique_ptr? I've not been able to come up with a solution without having to keep the original pointer passed to LegacyAllocator around.
Yes, you can use a custom deleter with std::unique_ptr or std::shared_ptr, for example:
struct Deleter {
void operator()(LegacyObj *p) const {
LegacyDeleter(&p);
}
};
std::unique_ptr<LegacyObj, Deleter> MakeLegacyObj() {
LegacyObj *p = 0;
LegacyAllocator(&p);
return std::unique_ptr<LegacyObj, Deleter>(p);
}
std::unique_ptr<LegacyObj, Deleter> p = MakeLegacyObj();
And, as correctly pointed out by #Dave, this works with shared_ptr too:
std::shared_ptr<LegacyObj> p = MakeLegacyObj();
You can use unique_ptr to delete the memory, but you'll have to provide a custom Deleter class since the memory is allocated using malloc rather than new.
Better yet, change the allocation code to use new instead and just use unique_ptr. If you go down this road you can just have the allocator return a unique_ptr instead of a pointer to the memory.
Assuming you need to provide your own custom deleter, here is one way you might do it:
template <typename T>
class MallocDeleter
{
public:
void operator() (T* obj) const
{
LegacyDeleter (*obj);
}
};
typedef std::unique_ptr <LegacyObj, MallocDeleter <LegacyObj>> unique_legacy_ptr;
You could also probably provide a make_unique_legacy type function which allocates by calling LegacyAllocator, instead of having to initialize the unique_ptr yourself.
You can create a factory function for unique_ptrs like this:
typedef void(* LegacyDeleterType)(LegacyObj*);
typedef std::unique_ptr<LegacyObj,LegacyDeleterType> UniqueLegacyPtr;
UniqueLegacyPtr makeUniqueLegacyObj()
{
LegacyObj * p = nullptr;
LegacyAllocator( &p );
return UniqueLegacyPtr( p, [](LegacyObj*p){ LegacyDeleter(&p); } );
}
You can now use that to create unique_ptrs and you can also assign to shared_ptrs which capture the custom deleter automatically at construction:
int main()
{
auto unique = makeUniqueLegacyObj();
std::shared_ptr<LegacyObj> shared = makeUniqueLegacyObj();
}

How to call virtual function of an object in C++ [duplicate]

This question already has an answer here:
Closed 10 years ago.
Possible Duplicate:
Overriding parent class’s function
I'm struggling with calling a virtual function in C++.
I'm not experienced in C++, I mainly use C# and Java so I might have some delusions, but bear with me.
I have to write a program where I have to avoid dynamic memory allocation if possible. I have made a class called List:
template <class T> class List {
public:
T items[maxListLength];
int length;
List() {
length = 0;
}
T get(int i) const {
if (i >= 0 && i < length) {
return items[i];
} else {
throw "Out of range!";
}
};
// set the value of an already existing element
void set(int i, T p) {
if (i >= 0 && i < length) {
items[i] = p;
} else {
throw "Out of range!";
}
}
// returns the index of the element
int add(T p) {
if (length >= maxListLength) {
throw "Too many points!";
}
items[length] = p;
return length++;
}
// removes and returns the last element;
T pop() {
if (length > 0) {
return items[--length];
} else {
throw "There is no element to remove!";
}
}
};
It just makes an array of the given type, and manages the length of it.
There is no need for dynamic memory allocation, I can just write:
List<Object> objects;
MyObject obj;
objects.add(obj);
MyObject inherits form Object. Object has a virtual function which is supposed to be overridden in MyObject:
struct Object {
virtual float method(const Input& input) {
return 0.0f;
}
};
struct MyObject: public Object {
virtual float method(const Input& input) {
return 1.0f;
}
};
I get the elements as:
objects.get(0).method(asdf);
The problem is that even though the first element is a MyObject, the Object's method function is called. I'm guessing there is something wrong with storing the object in an array of Objects without dynamically allocating memory for the MyObject, but I'm not sure.
Is there a way to call MyObject's method function? How? It's supposed to be a heterogeneous collection btw, so that's why the inheritance is there in the first place.
If there is no way to call the MyObject's method function, then how should I make my list in the first place?
Also I have no access to libraries outside of math.h and stdlib.h, so vector is not available for example.
You need to store pointers in the list. Try this:
List<Object*> objects;
Object *obj1 = new Object;
MyObject *obj2 = new MyObject;
Object *obj3 = new MyObject;
objects.add(obj1);
objects.add(obj2);
objects.add(obj3);
// This calls the implementation in Object class
objects.get(0)->method(asdf);
// This calls the implementation in MyObject class
objects.get(1)->method(asdf);
// This calls the implementation in MyObject class
// Polymorphism here
objects.get(2)->method(asdf);
Hope this helps.
When you do this:
objects.add(obj);
you are adding a copy of the Object part of the MyObject to the list, so it is no longer a MyObject.
You might be tempted to try doing this:
int add(T const &p) {
if (length >= maxListLength) {
throw "Too many points!";
}
items[length] = p; // now the problem is here
return length++;
}
but now the copy of the Object part of p happens during the assignment.
To make the list be heterogeneous, it is going to have to be a list of pointers, but you also wanted to avoid dynamic memory allocation. You can avoid dynamic memory allocation if you are careful:
Object obj1;
MyObject obj2;
List<Object*> object_ptrs;
object_ptrs.add(&obj1);
object_ptrs.add(&obj2);
 object_ptr.get(1)->method(input);
object_ptr.get(0)->method(input);
but again, you have to be very careful. The list is now pointing to the two objects on the stack. If you return from this function, those two objects will be destroyed. Note that I've purposefully put the list of object pointers after the objects, so that the list will get destroyed before the objects, so the list won't be left pointing to garbage. However, if you return a copy of the list, you would still have a problem.