Member objects, references and shared_ptr - c++

So, I've found myself doing this a lot, and wonder if it's correct practice (this probably won't compile - I'm writing this on my phone):
class Shared
{
private:
int _x;
public:
void X(int newValue) { _x = newValue; }
int X() { return _x; }
Shared(void) : _x(0)
{
}
};
class Owner
{
private:
shared_ptr<Shared> _shared;
public:
const Shared& Shared() const
{
return *_shared;
}
void Shared(const Shared& newValue)
{
_shared.reset(&newValue);
}
void DoSomethingWithShared()
{
/// yeah, this could be cleaner, not the point!
_shared.X(_shared.X() + 1);
}
};
void CreateStuff(Owner& a, Owner &b)
{
Shared s;
a.Shared(s);
b.Shared(s);
}
int main(int argc, char *argv[])
{
Owner a;
Owner b;
CreateStuff(a,b);
a.DoSomethingWithShared();
b.DoSomethingWithShared();
///...
/// "Shared" instance created in CreateStuff() hopefully lives until here...
}
The idea is that multiple instances of Owner need a shared resource of type Shared.
Is CreateStuff() an error? (ie, does s go out of scope, leaving a and b with invalid pointers to a destroyed object? (Am I returning the address of a temporary in a roundabout way?)
Are there any other scope/GC issues I'm not seeing?
Is there an easier way to do this?

CreateStuff is definitively wrong. You're (eventually) passing a pointer to a local variable into the shared_ptrs, which outlive that variable. Once it goes out of scope, you'll have two dangling pointers inside those _shareds.
Since you're using smart pointers, why not dynamically allocate that Shared on the heap, and let the smart pointers worry about deleting it when they're done?
void CreateStuff(Owner& a, Owner &b)
{
std::shared_ptr<Shared> s(new Shared);
a.Shared(s); // have that Shared() modified to take the shared_ptr,
b.Shared(s); // of course
}

Related

Do objects need to be deleted if stored in a map of pointers?

I'm starting to get a grasp on pointers and avoiding memory leaks...
I have one question though... Before I begin, I am NOT using C++11 so please don't reply with information on smart pointers and such that are specific to C++11...
I have the following code...
class Test
{
public:
Test(const int s_id, const std::string s_name) :
id(s_id),
name(s_name)
{
};
const int GetID()
{
return id;
}
private:
const int id;
const std::string name;
};
class TestCollection
{
public:
void AddTest(Test& my_test)
{
tests[my_test.GetID()] = &my_test;
}
void RemoveTest(const int id)
{
if (tests.find(id) != tests.end())
{
tests.erase(id);
}
}
public:
std::map<int, Test*> tests;
};
int _tmain(int argc, _TCHAR* argv[])
{
TestCollection collection;
Test my_test(0, "First Test");
collection.AddTest(my_test);
collection.RemoveTest(0);
return 0;
}
My question is do I need to do anything else to clear up the memory from my_test when I call RemoveTest? So as to avoid a memory leak?
I know that when I use the new keyword I need to call delete... But what do I do in this case?
Does it just get auto cleaned up by the garbage collector?
In the example both collection and my_test are allocated on the stack. As soon as the scope ends(return from _tmain) the memory will be released.
Taking pointers of stack variables that can exist outside the variable scope will result in unpredictable behavior. In this case if collection takes the object and stores the pointer rather than a copy.

RAII - store `void*&` or `void**`

I am working on design a wrapper class to provide RAII function.
The original use case is as follows:
void* tid(NULL);
OpenFunc(&tid);
CloseFunc(&tid);
After I introduce a new wrapper class, I expect the future usage will be as follows:
void* tid(NULL);
TTTA(tid);
or
TTTB(tid);
Question:
Which implementation TTTA or TTTB is better? Or they are all bad and please introduce a better one.
One thing I have concern is that after the resource is allocated, the id will be accessed outside of class TTTA or TTTB until the id is destroyed. Based on my understanding, my design should not have side-effect for that.
Thank you
class TTTA : boost::noncopyable
{
public:
explicit TTTA(void *id)
: m_id(id)
{
OpenFunc(&m_id); // third-party allocate resource API
}
~TTTA()
{
CloseFunc(&m_id); // third-party release resource API
}
private:
void* &m_id; // have to store the value in order to release in destructor
}
class TTTB : boost::noncopyable
{
public:
explicit TTTB(void *id)
: m_id(&id)
{
OpenFunc(m_id); // third-party allocate resource API
}
~TTTB()
{
CloseFunc(m_id); // third-party release resource API
}
private:
void** m_id; // have to store the value in order to release in destructor
}
// pass-in pointers comparison
class TTTD
{
public:
TTTD(int* id) // Take as reference, do not copy to stack.
: m_id(&id)
{
*m_id = new int(40);
}
private:
int** m_id;
};
class TTTC
{
public:
TTTC(int* &id)
: m_id(id)
{
m_id = new int(30);
}
private:
int* &m_id;
};
class TTTB
{
public:
TTTB(int* id)
: m_id(id)
{
m_id = new int(20);
}
private:
int* &m_id;
};
class TTTA
{
public:
TTTA(int** id)
: m_id(id)
{
*m_id = new int(10);
}
private:
int** m_id;
};
int main()
{
//////////////////////////////////////////////////////////////////////////
int *pA(NULL);
TTTA a(&pA);
cout << *pA << endl; // 10
//////////////////////////////////////////////////////////////////////////
int *pB(NULL);
TTTB b(pB);
//cout << *pB << endl; // wrong
//////////////////////////////////////////////////////////////////////////
int *pC(NULL);
TTTC c(pC);
cout << *pC << endl; // 30
//////////////////////////////////////////////////////////////////////////
int *pD(NULL);
TTTD d(pD);
cout << *pD << endl; // wrong
}
Both break in bad ways.
TTTA stores a reference to a variable (the parameter id) that's stored on the stack.
TTTB stores a pointer to a variable that's stored on the stack.
Both times, the variable goes out of scope when the constructor returns.
EDIT: Since you want the values modifiable, the simplest fix is to take the pointer as a reference; that will make TTTC reference the actual pointer instead of the local copy made when taking the pointer as a non reference parameter;
class TTTC : boost::noncopyable
{
public:
explicit TTTA(void *&id) // Take as reference, do not copy to stack.
: m_id(id)
...
private:
void* &m_id; // have to store the value in order to release in destructor
}
The simple test that breaks your versions is to add a print method to the classes to print the pointer value and do;
int main() {
void* a = (void*)0x200;
void* b = (void*)0x300;
{
TTTA ta(a);
TTTA tb(b);
ta.print();
tb.print();
}
}
Both TTTA and TTTB print both values as 0x300 on my machine. Of course, the result is really UB; so your result may vary.
Why do you tid at all? It’s leaking information to the client and makes the usage twice as long (two lines instead of one):
class tttc {
void* id;
public:
tttc() {
OpenFunc(&id);
}
~tttc() {
CloseFunc(&id);
}
tttc(tttc const&) = delete;
tttc& operator =(tttc const&) = delete;
};
Note that this class forbids copying – your solutions break the rule of three.
If you require access to id from the outside, provide a conversion inside tttc:
void* get() const { return id; }
Or, if absolutely necessary, via an implicit conversion:
operator void*() const { return id; }
(But use that one judiciously since implicit conversions weaken the type system and may lead to hard to diagnose bugs.)
And then there’s std::unique_ptr in the standard library which, with a custom deleter, actually achieves the same and additionally implements the rule of three properly.
What about wrapping it completely? This way you do not have to worry about managing the lifecycles of two variables, but only one.
class TTTC
{
void* m_id;
public:
TTTC()
: m_id(nullptr)
{
OpenFunc(&m_id); // third-party allocate resource API
}
TTTC(TTTC const&) = delete; // or ensure copying does what you expect
void*const& tid() const { return m_id; }
~TTTC()
{
CloseFunc(&m_id); // third-party release resource API
}
};
Using it is simplicity itself:
TTTC wrapped;
DoSomethingWithTid(wrapped.tid());

copy local objects by reference

Here's my problem,
Class MClass {
public:
void Add(OtherClass* objects) {
_objects = objects;
}
private:
OtherClass* _objects;
}
//otherfile.cpp
void Setup() {
MClass myObj;
OtherClass obj[NUMBER_OF_OBJECTS];
//obj initialization here
//...
myObj.Add(obj);
}
It will cause a RT error because the *obj diminishes after the end of the function body.
But, how can make this one valid?
I like to initialized first an object before assigning it to other class.
EDIT
I don't want to use storage classes or something here, I just want a raw array since it is very expensive for me to use. Its functionality will not lessen my problem here.
So how do I do that in a raw-array style?
Class MClass {
public:
void Add(std::vector<OtherClass> objects) {
_objects = std::move(objects);
}
private:
std::vector<OtherClass> _objects;
}
//otherfile.cpp
void Setup() {
MClass myObj;
std::vector<OtherClass> obj(NUMBER_OF_OBJECTS);
myObj.Add(std::move(obj));
}
In your example, you store a pointer to a local array. If the method ends, the array goes out of scope and doesn't exist anymore.
This is the reason, your pointer is not valid anymore. If you want to solve this, learn about the scope of variables in C++.
It is not completely clear what you are trying to do, but you could store a collection of objects instead of a pointer:
class MClass
{
public:
void Add(const std::vector<OtherClass>& objects) {
objects_ = objects;
}
void Add(std::vector<OtherClass>&& objects) {
objects_ = std::move(objects);
}
private:
std::vector<OtherClass> objects_;
};
then
void Setup()
{
MClass myObj;
std::vector<OtherClass> obj(NUMBER_OF_OBJECTS);
//obj initialization here
//...
myObj.Add(std::move(obj)); // move obj's contents onto myObs's objects.
}
Stop using raw arrays, and use either std::vector or std::array. Then you don't have to worry about it anymore.
If you really want to do it manually, you have to copy is manually as well. Using e.g. std::vector and std::move is more effective, but here you go:
Class MClass {
public:
MClass()
: _objects(nullptr), _count(0)
{}
MClass(const MClass& other)
: _objects(nullptr), _count(0)
{
Add(other._objects, other._count);
}
~MClass()
{
if (_objects != nullptr)
delete [] _objects;
}
void Add(const OtherClass* objects, const size_t count)
{
if (_objects != nullptr)
delete [] _objects;
_objects = new [count];
for (size_t i = 0; i < count; i++)
_objects[i] = objects[i];
_count = count;
}
MClass& operator=(const MClass& other)
{
Add(other._objects, other._count);
}
private:
OtherClass* _objects;
size_t _count;
};
// ...
myObj.Add(obj, NUMBER_OF_OBJECTS);
As you can see, it's a lot of more code, which makes it harder to follow and debug, and also larger possibility of errors. And not as "effective" as I said above.

c++ vector losing pointer reference

I should get the same in both lines..
what happen I get two different values.. like it was aiming to different positions..
I think the error is inside the d->add(*b)
the output is
thiago 14333804
Ph¿├┌ 2816532
to describe it better I put the code below
I got a program
int main(int argc, char **argv) {
CClass* c = new CClass();
BClass* b = c->getNext();
printf("%s %d \n", b->getValue(), b->getValue());
DClass* d = new DClass();
d->add(*b);
printf("%s %d \n", d->getNext(), d->getNext());
cin.get();
return 0;
}
the interfaces are below
class BClass
{
private:
char* value;
bool stale;
public:
BClass(char* value);
~BClass(void);
char* getValue();
bool isStale();
};
class CClass
{
private:
vector<BClass*> list;
public:
CClass(void);
~CClass(void);
BClass* getNext();
};
class DClass
{
private:
vector<BClass*> list;
static bool isStale(BClass* b) { return b->isStale();};
public:
DClass(void);
~DClass(void);
void add(BClass s);
char* getNext();
};
and the implementation follows
//BClass
BClass::BClass(char* value)
{
this->value = value;
this->stale = false;
}
BClass::~BClass(void)
{
}
char* BClass::getValue()
{
return value;
}
bool BClass::isStale()
{
return stale;
}
//CClass
CClass::CClass(void)
{
list.push_back(new BClass("thiago"));
list.push_back(new BClass("bruno"));
list.push_back(new BClass("carlos"));
}
CClass::~CClass(void)
{
}
BClass* CClass::getNext()
{
return list.at(0);
}
//DClass
DClass::DClass(void)
{
}
DClass::~DClass(void)
{
}
void DClass::add( BClass s )
{
list.push_back(&s);
}
char* DClass::getNext()
{
BClass* b = list.at(0);
return b->getValue();
}
When you pass in an instance of class B into D::add() function you create a deep copy of the object and that copy is what is put on stack. Later on you use the address of that copy to push it into list. Once the function is done this automatic variable goes out of scope thus the pointer you used to put into list is no longer valid.
To fix change your interface to avoid deep copies as follows:
void DClass::add( BClass * s )
{
list.push_back(s);
}
Step-by-step of what your code is doing
BClass* b = c->getNext(); // you get the address of the first element from the list (created in constructor) and assign it to b
d->add(*b); // the *b will dereference the object pointed to by b and put it onto stack in preparation to the call to add()
void DClass::add( BClass s ){ // the deep copy of a dereferenced object is put into this function's stack frame
list.push_back(&s); // an address of that temporary copy of the original object is being used to be added to your list
} // this is where the fun happens - once the function is done it will unwind the stack back up and the memory, previously occupied by that temp copy, will be re-used for other purposes. In your case - it will be used to pass parameters to functions d->getNext() (there's always a hidden this parameter to non-static member functions) and later to the printf() function. Remember - your previous pointer to that temp copy is still pointing to the stack, but it's now occupied by different data, causing you to see corruption
General rule of thumb - never use pointers to temp objects ;-)
in the DClass::add function, BClass s is a local variable.
void DClass::add( BClass s )
{
list.push_back(&s);
}
When you call d->add(*b);, you're passing a BClass by value, meaning you're creating a copy of it, and the address of that copy is not the same address of the original.
s will go out of scope as soon as the function returns, and the pointer to it will be invalid. So storing that pointer is no good to you, since dereferencing it would be undefined behaviour.

C++ pointer to pointer scope issue

I have a list where I store a pointer to a pointer of objects. I have a function where I create pointers to these objects and store their addresses in the list (hence pointer to a pointer). However once this function is done that pointer is no longer valid (the object is but not the pointer because it's out of scope) so now my pointer to pointer doesn't work. How do you get around this?
list<Actor**> lst;
void CreateEnemy()
{
Actor* a = new Actor();
lst.push_back(&a);
}
int _tmain(int argc, _TCHAR* argv[])
{
CreateEnemy();
// at this point the pointer to a pointer stored in lst isn't valid anymore because it went out of scope after CreateEnemy() completed.
}
Here's a simple example of something you could do based on your comments.
list<unique_ptr<Actor>> lst;
void CreateEnemy()
{
lst.push_back(unique_ptr<Actor>(new Actor));
}
void KillRandomEnemies()
{
for (auto& i : lst)
{
if (rand() % 100)
i.reset();
}
}
class Projectile
{
public:
Projectile(unique_ptr<Actor> & a)
:actor(&a)
{}
bool IsTargetDead() const { return !(*actor); }
private:
unique_ptr<Actor> * actor;
};
int main()
{
CreateEnemy();
Projectile proj(lst.front());
while (something())
{
KillRandomEnemies();
if (proj.IsTargetDead())
whatever();
}
}
Just use std::list<Actor*> and store the pointer. Or, even better, std::list<Actor>. There's nothing here that suggests a need for any pointers, much less a pointer to a pointer.
Try this :
after the call to createEnemy :
Actor * a = * lst.front();
a -> some function.
Is this still doing problems?
I tested the code on my own class and it was fine.