There is an equivalent codification in C++ with smartpointers for this code?
In External.cpp:
class ExampleClass {...};
ExampleClass* function()
{
ExampleClass *ptr = new ExampleClass();
ptr->doSomething();
return ptr;
}
In Another.cpp i would like to do something like this properly, how?:
ExampleClass *ptr2 = function();
There are two actually, you could use either unique_ptr or shared_ptr, look here when to use which: Which kind of pointer do I use when?
I'f you'd opt for the unique_ptr, then you'd get:
class ExampleClass {...};
std::unique_ptr<ExampleClass> function()
{
std::unique_ptr<ExampleClass> uptr = std::make_unique<ExampleClass>();
uptr->doSomething();
return std::move(uptr);
}
//In Another.cpp
std::unique_ptr<ExampleClass> ptr2 = function();
//you could even store the result in a shared pointer!!
std::shared_ptr<ExampleClass> ptr3 = function();
I won't really recommend it, but you can return an object that implicitly converts to a raw pointer. It will own it for a short duration, and delete if no-one grabs it.
struct RelinquishOrDelete {
ExampleClass *_ptr;
operator ExampleClass*() { auto ret = _ptr; _ptr = nullptr; return ret; }
~RelinquishOrDelete() {
if(!_ptr) {
cerr << "returned object wasn't taken by a new owner\n";
delete _ptr;
}
}
};
Using it is simple. It will pack and unpack the pointer in this simple case:
RelinquishOrDelete function()
{
ExampleClass *ptr = new ExampleClass();
ptr->doSomething();
return {ptr};
}
// ...
ExampleClass *ptr2 = function();
But of course, it will likely cause unexpected behavior if used in this perfectly reasonable piece of code:
auto ptr3 = function();
A smart pointer with much stricter ownership semantics is really the best approach.
Lets say I have the following:
int main() {
int* test = new int;
*test = 5;
int* test2 = test;
}
Then, somewhere, in some function , I deallocate memory for test2 and set it to NULL. Is there a way to set test to NULL, in the same function without passing it to the function?
EDIT: std::shared_ptr cannot be used
The shared_ptr and weak_ptr classes do exactly what you want. Since you can't use them, your best option is to re-implement just the portions of them that you need. I'm going to assume you don't need any thread safety and that you don't care about optimizations for simplicity. If you do, use the standard library.
You need a control object. It should have a pointer to the real object and two integers, one the count of strong pointers, the other the count of weak pointers. Strong pointers and weak pointers should have a pointer to the control object.
When a strong pointer is destroyed, decrement the strong pointer count. If the strong pointer count is zero, delete the object and set its pointer to NULL. If the weak pointer count is also zero, discard the control object.
When a weak pointer is destroyed, decrement the weak pointer count. If both pointers counts are zero, discard the control object.
When pointers are copied, you must bump the count. When a weak pointer is promoted to a strong pointer, bump the strong pointer count and fail the operation if it was previously zero.
That should be enough to give you the idea.
Pass the pointer be reference, since a copy would be passed to the function had you used a normal pointer, on which you can only change the pointed value, and since both pointers point to the same thing, no need to call change() on both:
#include <iostream>
void change(int*& p)
{
delete p;
p = nullptr;
}
int main()
{
int* test = new int;
*test = 5;
int* test2 = test;
std::cout << *test; //5
std::cout << *test2; //5
change(test);
}
Example
BTW, I recommend std::shared_ptr for a purpose like this, or std::unique_ptr
EDIT
The only problem above is that test2 is deleted, not pointing to nullptr, but that cannot be changed unless with smart pointers or a different function.
By default, when you pass a pointer to a function, you are passing a copy of the value:
void f(int* p) {
// p has the same value as x below, but is independent
delete p;
p = nullptr;
// p is null, but back in main 'x' still has the original value
}
int main() {
int* x = new int;
f(x);
// 'x' is unmodified and now points to a deleted block of memory
}
Your options are to pass the pointer by reference or pass a pointer to the pointer:
#include <iostream>
void by_pointer(int** p) {
delete *p;
*p = nullptr;
}
void by_reference(int*& p) {
delete p;
p = nullptr;
}
int main() {
int* x = new int;
by_pointer(&x);
std::cout << (void*)x << "\n"; // outputs null
int* y = new int;
by_reference(y);
std::cout << (void*)y << "\n"; // outputs null
}
If you really want this (though I'd strongly suggest you to reconsider your design), then the following might work for you:
We wrap the pointer in a structure/class to be able to "hook" us on construction and destruction of such pointers:
template<typename T>
struct pointer {
Since when freeing the stored value, we also need to modify all pointers that still point to it, we need to keep track of them somehow. I'd say just store them alongside the value:
struct boxing {
T value;
std::set<pointer<T> *> references;
};
boxing * box;
Next comes constructing a pointer. I simplified here. You might want to add perfect forwarding, a possibility to construct a "null pointer", and so on ...
pointer(T value) : box(new boxing{value}) {
add_myself();
}
As you see, we "add ourselves" (to the set of references). When the pointer is destructed, we need to remove ourselves from that set again:
~pointer() {
remove_myself();
}
When being copy constructed, we just use the box from the original and add ourselves:
pointer(pointer const & p) : box(p.box) {
add_myself();
}
When being copy assigned to, we first need to remove ourselves from the current box, use the box of the original and add ourselves:
pointer & operator=(pointer const & p) {
remove_myself();
box = p.box;
add_myself();
}
I'm lazy. Implement move construction / assignment yourself ;)
pointer(pointer &&) = delete;
pointer & operator=(pointer &&) = delete;
We want to be able to use the pointer, so we add a conversion operator to a raw pointer:
operator T*(void) {
return box ? &(box->value) : nullptr;
}
Finally, freeing a pointer. We set all box members of the current pointers in the references set to nullptr (this includes ourself, thus the additional pointer b), and then delete the box:
void free() {
boxing * b = box;
for (pointer * p : b->references) {
p->box = nullptr;
}
delete b;
}
Oh, and last but not least, adding and removing ourselves:
private:
void remove_myself() {
if (box == nullptr) return;
box->references.erase(this);
if (box->references.size() == 0) {
delete box;
}
}
void add_myself() {
if (box == nullptr) return;
box->references.insert(this);
}
};
Some function. Note that I pass by value to force another copy construction:
void foo(pointer<int> p) {
p.free();
}
Two pointers, pointing to the same boxed value:
int main(int, char **) {
pointer<int> a{21};
pointer<int> b = a;
*b = 42;
std::cout << *a << std::endl;
foo(a);
std::cout << "a is " << ((a == nullptr) ? "null" : "non-null") << std::endl;
return 0;
}
Above example on ideone.
The idea of shared controllers of a uniquely-owned object is of course horrid (for reasons that will become clear).
Nevertheless, it can be done:
template<class T, class Deleter = std::default_delete<T>>
struct shared_unique
{
struct control_block
{
control_block(Deleter del, T* p) : del_(std::move(del)), ptr_(p), refs_(1) {}
Deleter del_;
T* ptr_;
std::size_t refs_;
void addref()
{
++refs_;
}
void release()
{
if (--refs_ == 0)
delete this;
}
~control_block() {
if (ptr_)
del_(ptr_);
}
};
control_block* ctrl_;
shared_unique(T* p = nullptr, Deleter del = Deleter()) : ctrl_(new control_block(std::move(del), p)) {}
shared_unique(shared_unique const& r) : ctrl_(r.ctrl_) { ctrl_->addref(); }
shared_unique& operator=(shared_unique const& r)
{
auto tmp = r;
swap(r);
return *this;
}
shared_unique(shared_unique&& r) : ctrl_(r.ctrl_) { r.ctrl_ = nullptr; }
shared_unique& operator=(shared_unique&& r)
{
auto tmp = std::move(r);
swap(tmp);
return *this;
}
~shared_unique()
{
ctrl_->release();
}
void swap(shared_unique& r) noexcept
{
std::swap(ctrl_, r.ctrl_);
}
void reset(T* p = nullptr)
{
std::swap(ctrl_->ptr_, p);
delete p;
}
T* get() const {
return ctrl_->ptr_;
}
};
int main()
{
shared_unique<int> su1(new int(5));
assert( su1.get() );
assert( *(su1.get()) == 5 );
shared_unique<int> su2 = su1;
assert( su2.get() );
assert( *(su2.get()) == 5 );
su1.reset();
assert( su1.get() == nullptr );
assert( su2.get() == nullptr );
}
The problem is that it is impossible to make this arrangement thread-safe, unless you provide some kind of 'lock' mechanism to keep the pointed-to object alive while it's being accessed.
If you want to know when an object has been destroyed, it's probably better to have it (or its smart pointer) emit a signal when this happens and have the interested observers listen on the slot (or similar).
i have the following problem:
i have a pointer to a function as a member of class B which exists in an encapsulating class A.
Class A
{
public:
ObjAbs* CreateObject(int id);
private:
Class B
{
typedef ObjAbs* (B::*pfnObjAlloc)();
pfnObjAlloc mfnAlloc;
MemPool* mpPool;
template<typename T>
ObjAbs* TAlloc()
{
ObjAbs* pObj = NULL;
void *memory = NULL;
if(mpMemPool)
memory = mpMemPool->Alloc();
if (NULL != memory)
param = new (memory) T();
return ObjAbs;
}
}
B mAllocArr[maxObjsId];
A::A()
{
mAlloArr[id1] = &A::B::TAlloc<Obj1>;
mAlloArr[id2] = &A::B::TAlloc<Obj2>;
.
.
.
}
}
I am trying to access it from class A in the following manner:
ObjAbs* A::CreateObject(int id)
{
ObjAbs* pObj = NULL;
if(NULL != AllocArr[id].mfnAlloc)
pObj = (AllocArr[id].*mfnAlloc)(); <-- There lies the problem
return pObj;
}
i keep getting the following error:
error C2065: 'mfnAlloc' : undeclared identifier
Can someone help me?
Thanks,
pObj = (AllocArr[id].*mfnAlloc)();
tries to look up mfnAlloc in the current scope, not in B's.
The syntax for calling a pointer-to-member-function is (object.*function)(), and since both object and function are evaluated in the current scope, you need something more like
(AllocArr[id].*(AllocArr[id].mfnAlloc))();
which is a hideous mess of code, so it's probably a better idea to add another member function to B:
ObjAbs* allocate()
{
return (*mfnAlloc)();
}
so you can write the more readable
pObj = AllocArr[id].allocate();
I want to create a C++ objects factory that will create some objects by id. Each object must have a references counter. If an object with the same id is requested again, the same object must be returned if it's still in memory.
While there is something keeping a pointer to an object, this object will not be deleted. When there is no pointers to the object but pointer in factory cache, this object is placed in QCache and will be deleted if it will not be requested again for some time.
What's the best way to implement this?
Here is how I would do it.
First of all, the factory class would only hold observing pointers to the objects it instantiates. This way, objects will be immediately deleted when no owning references to them exist, without putting them in a queue.
Then, the factory class would return shared pointers to the objects it instantiates, and those shared pointers would specify a custom deleter to unregister the deleted object from the factory's map upon destruction.
Assuming that the objects you want to instantiate have a constructor which accept their ID as an argument, and a function get_id() to return their ID, here is the code for the factory class:
#include <memory>
#include <unordered_map>
#include <functional>
using namespace std;
using namespace std::placeholders;
template<typename T>
class factory
{
public:
shared_ptr<T> get_instance(int id)
{
auto i = m_map.find(id);
if (i == m_map.end())
{
return create(id);
}
else
{
shared_ptr<T> p = i->second.lock();
if (p == nullptr)
{
p = create(id);
}
return p;
}
}
shared_ptr<T> create_instance()
{
shared_ptr<T> p = create(nextId);
nextId++;
return p;
}
void unregister(T* p)
{
int id = p->get_id();
m_map.erase(id);
delete p;
}
private:
shared_ptr<T> create(int id)
{
shared_ptr<T> p(new T(id), bind(&factory::unregister, this, _1));
m_map[id] = p;
return p;
}
unordered_map<int, weak_ptr<T>> m_map;
int nextId = 0;
};
And that's how you would use it:
struct A
{
A(int id) : _id(id) { }
int get_id() const { return _id; }
int _id;
};
int main()
{
factory<A> f;
{
shared_ptr<A> pA = f.get_instance(5);
shared_ptr<A> pB = pA;
// ...
// The object with ID 5 will go out of scope and get unregistered
}
shared_ptr<A> pA = f.get_instance(3);
shared_ptr<A> pB = f.get_instance(3); // This will return the existing object
//
// Instance with ID 3 will go out of scope and get unregistered
}
I have this problem:
void myFunc()
{
MyClass * myInstance = NULL;
newInstance(myInstance);
}
void newInstance(MyClass * instance)
{
instance = new MyClass(...);
}
the code seems to work fine, but when I exits from newInstance function, my myInstance is null and not with the values that have inside newInstance... where is the problem?t
thanks
The pointer is copied into newInstance and then you change the value of that copy. If you want to modify the pointer inside the function, you need to pass it by reference:
void newInstance(MyClass*& instance)
{
instance = new MyClass(...);
}
Or alternatively, you could pass a MyClass** and do *instance = new Class(...);.
Either way, it would be preferable to actually return the pointer instead of passing it as a modifiable argument.
void myFunc()
{
MyClass * myInstance = newInstance();
delete myInstance;
}
MyClass* newInstance()
{
return new MyClass(...);
}
Of course, you will have to remember to delete the object. To avoid this, you can make it safer by using smart pointers:
void myFunc()
{
auto myInstance = newInstance();
}
std::unique_ptr<MyClass> newInstance()
{
return std::unique_ptr<MyClass>(new MyClass(...));
}
You would need to pass a refetence to a pointer, or return the pointer from the function:
void newInstance(MyClass*& instance)
{
instance = new MyClass(...);
}
MyClass* newInstance()
{
return new MyClass(...);
}
But you don't want to deal with raw pointers to dynamically allocated memory. What you really need is to use smart pointers here, particularly std::unique_ptr.