After member function delete the current instance,how to stop the behind code executes.
See the code.
#include <iostream>
class A;
void callfun(int i,A *pt);
class A {
public:
A() { sss="this is A."; }
virtual ~A() {}
void foo(int i) {
callfun(i,this); //call a function.Don't return value.Maybe delete instance.
out();
}
private:
void out() {
std::cout<< "Out:" <<std::endl;
std::cout<< sss << std::endl;
}
std::string sss;
}
void callfun(int i,A *pt) {
if (i==0)
delete pt; //If conditions are matched,delete instance.
}
int main() {
A *a1=new A;
a1->foo(1); //print:Out:this is A.
a1->foo(0); //delete a1,don't print.But in fact it would print.how to do?
}
I want the result:foo(1) output "Out:this is A.",foo(0) delete instance,don't output.
Disclaimer: this is bad. bad. Terrible.
void foo(int i) {
if ( i == 1)
{
callfun(i,this); //call a function.Don't return value.Maybe delete instance.
out();
}
else
{
delete this;
}
}
Note that after you've done delete this; (cases where this is actually needed are rare) it's illegal to call any non-static functions on your instance, access the pointer (both inside or outside the method) or access any data members.
This is impossible, given the comments which state that foo shouldn't be aware of the deletion. That itself make the very next line Undefined Behavior. If callfun calls delete this, then foo MUST return immediately without even looking at this. Therefore you can't even set a "deleted" flag in this.
The closest I get is
void callfun(int i, A *pt) {
if (i==0) {
delete pt;
throw 0;
}
}
void A::foo(int i) {
try {
callfun(i,this); // No _visible_ return value.
out();
} catch (int) { }
}
If you delete internally, how does the enclosing scope know that its been deleted? You should just mark it and leave it up to the user/enclosing scope to actually dispose it.
The following is a more complete code.
class A;
class B {
public:
void creat() {
pp=new A;
}
void remove() {
delete pp;
pp=NULL;
}
private:
A *pp;
};
class A {
public:
void foo(int i) {
callfun(i,this);
if (flag)
out();
else
bb->remove();
}
private:
B *bb;
};
Related
New to c++ and OOP. I'm trying to figure out lists and iteration, so I've created the following example code. I create a couple Thing objects, but I want to make sure that when a Thing is created, its constructor adds it to a list "things" (inside the lists object) so that I can keep track of every instance of Thing. At the bottom of main() I then iterate through the list of Things. Is there a better way to do this, or could you point out how to do this in my Thing constructor? Thanks!!
#include <iostream>
#include <list>
class Thing;
class Lists
{
public:
std::list<Thing> things;
Lists() {
std::cout << "List object with list 'things' created" << std::endl;
}
};
class Thing
{
public:
int howMuch, pointer;
Thing(int x, Lists* y)
{
howMuch = x;
y->things.push_back(this);
}
};
int main()
{
//create the object that holds the list of things
Lists lists;
//make some objects, and pass a pointer of the lists to the constructor
Thing thingA(123, &lists);
Thing thingB(456, &lists);
for (std::list<Thing>::iterator it = lists.things.begin(); it != lists.things.end(); ++it)
std::cout << "test" << it->howMuch << std::endl;
return 0;
}
You can store created items inside the Thing class itself using a static field _things:
#include <iostream>
#include <list>
class Thing
{
static std::list<Thing> _things;
public:
int howMuch, pointer;
Thing(int x) : howMuch(x)
{
_things.push_back(*this);
}
static std::list<Thing> getAllThings()
{
return _things;
}
};
std::list<Thing> Thing::_things;
int main()
{
Thing thingA(123);
Thing thingB(456);
auto allThings = Thing::getAllThings();
for (auto it = allThings.begin(); it != allThings.end(); ++it)
std::cout << "test " << it->howMuch << std::endl;
return 0;
}
The original example and the example in answer 1 encounter problems as soon as any Thing is destroyed (as François Andrieux mentioned), even if you use a pointer to Thing in the list. If you use a Thing in a subroutine as a local variable, the Thing is destroyed at the end of this function, but is still in the list. To solve this problem, you have to remove the Thing from the list in the destructor of Thing. But if you do so, you get a problem, when Thing is a global object. You have two global objects - the list and the Thing. It is not clear, which is destroyed first, so you can end up whith an access violation, which is difficult to debug, because it happens after exit().
Here is my proposal:
template<class T>
class InstanceIterator{ // Iterator for an InstanceList
public:
InstanceIterator(T*pT)
: pt(pT)
{}
T& operator*(){ return *pt; }
T* operator->(){ return pt; }
InstanceIterator operator++(){
pt=pt->instanceList.pNext;
return *this;
}
int operator!=(const InstanceIterator<T>& i){ return i.pt!=pt; }
private:
T*pt;
};
template<class T>
class InstanceList{
// this class means not the whole list, but only the element (pNext)
// which is inserted into the object you want to have in a list.
// there is no explizite list, every instance class T has a part of the list
public:
InstanceList(){};
void insert(T* pt){ // gets the this-pointer of the surrounding class
pNext=pFirst;
pFirst=pt;
}
~InstanceList();
static InstanceIterator<T> begin(){ return pFirst; }
static InstanceIterator<T> end(){ return 0; }
static bool empty(){ return pFirst==0; }
private:
InstanceList(const InstanceList&);// no copy constructor
void operator=(const InstanceList&);// no assignment
static T* pFirst;
T* pNext;
friend class InstanceIterator<T>;
};
template<class T>
InstanceList<T>::~InstanceList(){
T**ppInst=&pFirst;
// search for myself
while(&((*ppInst)->instanceList)!=this) { // its me?
if(0==(*ppInst)) {
return; // emergency exit
}
ppInst=&((*ppInst)->instanceList.pNext); // the next please
}
// and remove me from the list
(*ppInst)=pNext;
}
template<class T>
T* InstanceList<T>::pFirst=0;
// how to use and test the above template:
// (uses 3 objects: one is global, one is local,
// and one is deleted before going through the list)
class InstanceTest { // example class, the instances of this class are listed
public:
InstanceTest(int i)
: i(i)
{
instanceList.insert(this); // dont forget this line
}
InstanceList<InstanceTest> instanceList; // must have this line with exact this name
int i;
};
InstanceTest t1(1); // a global object
int main() {
std::cout << "testing InstanceIterator";
InstanceTest t2(2); // a local object
InstanceTest* pt3 = new InstanceTest(3); // will be deleted later
int sum(0);
for(InstanceIterator<InstanceTest> it= InstanceList<InstanceTest>::begin(); it!= InstanceList<InstanceTest>::end();++it){
sum += it->i;
}
int testFailed(0);
if (sum != 6) testFailed++;
delete pt3;
sum = 0;
for (InstanceIterator<InstanceTest> it = InstanceList<InstanceTest>::begin(); it != InstanceList<InstanceTest>::end(); ++it) {
sum += it->i;
}
if (sum != 3) testFailed++;
if (testFailed) {
std::cout << "... FAILED !!!\n";
}
else std::cout << "... OK\n";
return testFailed;
}
I have an object which contains a thread which indirectly accesses this object like so:
#include <iostream>
#include <thread>
#include <atomic>
class A;
class Manager
{
public:
Manager(void) = default;
void StartA(void)
{
a = std::make_unique<A>(*this);
}
void StopA(void)
{
a = nullptr;
}
A& GetA(void)
{
return *a;
}
private:
std::unique_ptr<A> a;
};
class A
{
public:
A(Manager& manager)
: manager{manager},
shouldwork{true},
thread{[&]{ this->Run(); }}
{
}
~A(void)
{
shouldwork = false;
thread.join();
}
private:
Manager& manager;
std::atomic<bool> shouldwork;
std::thread thread;
void Run(void)
{
while (shouldwork)
{
// Here goes a lot of code which calls manager.GetA().
auto& a = manager.GetA();
}
}
};
int main(int argc, char* argv[])
try
{
Manager man;
man.StartA();
man.StopA();
}
catch (std::exception& e)
{
std::cerr << "Exception caught: " << e.what() << '\n';
}
catch (...)
{
std::cerr << "Unknown exception.\n";
}
The problem is that when one thread calls Manager::StopA and enters destructor of A, the thread inside A segfaults at Manager::GetA. How can I fix this?
In StopA() you set a = nullptr;, this in turn destroys the a object and all further access to its members result in undefined behaviour (a likely cause the segmentation fault).
Simply moving the a = nullptr; to the destructor of the Manager could resolve this problem. Even better, allow the RAII mechanism of the std::unique_ptr to destroy the a object when the destructor of the Manager runs (i.e. remove the line of code completely).
With active object implementations, careful control of the member variables is important, especially the "stop variable/control" (here the shouldwork = false;). Allow the manager to access the variable directly or via a method to stop the active object before its destruction.
Some of the code here looks out of place or obscure, e.g. a = std::make_unique<A>(*this);. A redesign could help simplify some of the code. The Manager class could be removed.
class A
{
public:
A(): shouldwork{true}, thread{[&]{ this->Run(); }}
{
}
void StopA()
{
shouldwork = false;
thread.join();
}
private:
std::atomic<bool> shouldwork;
std::thread thread;
void Run(void)
{
while (shouldwork)
{
// code...
}
}
};
The code is modelled along the lines of std::thread, were the stopping of the tread is more controlled before an attempt is made to join it. The destructor is left empty in this case, to mimic the termination (calling std::terminate) result, as is the case with the standard thread library. Threads must be explicitly joined (or detached) before destruction.
Re-introducing the Manager, the code could look as follows;
class A
{
public:
A() : shouldwork{true}, thread{[&]{ this->Run(); }} {}
void StopA() { shouldwork = false; thread.join(); }
private:
void Run();
std::atomic<bool> shouldwork;
std::thread thread;
};
class Manager
{
public:
Manager() = default;
void StartA(void)
{
a = std::make_unique<A>();
}
void StopA(void)
{
a->StopA();
}
A& GetA(void)
{
return *a;
}
private:
std::unique_ptr<A> a;
};
void A::Run()
{
while (shouldwork)
{
// Here goes a lot of code which calls manager.GetA().
auto& a = manager.GetA();
}
}
And your main remains as it is.
I was trying to write a sample code for implementing shared pointer [just for practice].
In this following example,
why compiler is not complaining about modifying other_T
And why copy constructor SharedPtr(const T& other_T) is not getting called ?
Here is the code snippet.
#include <iostream>
using namespace std;
#define DBG cout<<"[DEBUG]"<<__PRETTY_FUNCTION__<<endl
class RefCount
{
protected:
int m_ref;
RefCount(){ DBG; m_ref = 1 ; }
void reference(){ DBG; ++m_ref; }
void dereference(){ DBG;--m_ref; }
};
template <class T>
class SharedPtr : public RefCount
{
T* m_T;
public:
SharedPtr() { DBG; m_T = new T; }
SharedPtr(const T& other_T){
DBG;
m_T = other_T.m_T;
other_T.dereference();
other_T.m_T = NULL;
}
~SharedPtr() {
DBG;
dereference();
cout<<m_ref<<endl;
if(m_ref <= 0 && m_T != NULL ){
cout<<"Destroying"<<endl;
delete m_T;
m_T = NULL;
}
}
};
class A{};
int main()
{
SharedPtr<A> obj;
cout<<"assigning "<<endl;
SharedPtr<A> obj2 = obj;
cout<<"END"<<endl;
return 0;
}
and the result is segfault.
Your primary problem is that the copy constructor is being called--but you haven't defined a copy constructor, so you're getting the copy constructor that's defined by the compiler by default.
That copy constructor just does a member-wise copy. That means you've allocated one A with new, then pointed two SharedPtr objects at that same A. The first one to get destroyed deletes the A object. Then the second one gets destroyed, attempts to delete the same object again, and havoc ensues.
In the end, it doesn't look to me like much (any?) of this is going to make any real difference though. I'm pretty sure your basic design is broken. To get a working shared pointer, you have one reference count and "raw" pointer to the final object. Then you have N SharedPtr objects referring to that one ref count/pointer structure that in turn refers to the final object.
You're trying to combine the raw pointer/ref count into the individual SharedPtr, and I don't see any way that can actually work.
It also seems to me that the basic concept of what you've called a RefCount is really part of the design of a SharedPtr. As such, I think its definition should be nested inside that of SharedPtr (and probably made private, since the outside world has no reason to know it exists, not to mention being able to access it directly).
With those taken into account, the code might end up something like this:
#include <iostream>
using namespace std;
#define DBG cout<<"[DEBUG]"<<__PRETTY_FUNCTION__<<endl
template <class T>
class SharedPtr {
template <class U>
struct Ref {
mutable int m_ref;
U *data;
Ref(T *data) : m_ref(1), data(data) { DBG; }
void add_ref() const { DBG; ++m_ref; std::cout << "m_ref=" << m_ref << "\n"; }
void sub_ref() const { DBG; --m_ref; std::cout << "m_ref=" << m_ref << "\n"; }
~Ref() { delete data; }
};
Ref<T> *r;
public:
SharedPtr(T *data) { DBG; r = new Ref<T>(data); }
SharedPtr(SharedPtr const &p) : r(p.r) { DBG; r->add_ref(); }
~SharedPtr() {
DBG;
r->sub_ref();
if (0 == r->m_ref) {
delete r;
std::cout << "deleted pointee\n";
}
}
};
class A{};
int main() {
SharedPtr<A> obj(new A);
cout<<"copying "<<endl;
SharedPtr<A> obj2 = obj;
cout<<"END"<<endl;
return 0;
}
Notes: though this fixes at least some of the basic design, it's still quite a ways short of usable. It's missing the dereference operator, so you can't use the pointer to get to the value it points at. It'll break completely in a multi-threaded environment. I haven't thought enough about it to be sure, but my immediate guess is that it's probably not exception safe either.
I need to pass a pointer to a class so some code I don't control. This code automatically free()s the pointer when it is done, but I need the class later. I hoped I could just make a 'wrapper' class that would keep the class from being deallocated without actually preventing the code from accessing it, but virtual calls don't work.
template <class T>
class PointerWrapper:public T
{
public:
T* p;
PointerWrapper(T *ptr)
{
p=ptr;
}
~PointerWrapper(void)
{
}
T* operator->() const
{
return p;
}
T& operator*() const
{
return *p;
}
};
void codeIDontControl(Example *ex)
{
ex->virtualfunction();
delete ex;
}
void myCode()
{
Example *ex=new Example();
codeIDontControl(ex);
do something with ex //doesn't work because ex has been freed
codeIDontControl(new PointerWrapper<Example>(ex));
do something with ex //ex hasn't been freed, but the changes made to it via
// Example::virtualfunction() in codeIDontControl() aren't there anymore
}
Basically, ex->virtualfunction() calls the virtual function in PointerWrapper itself instead of the virtual function in PointerWrapper->p. It seems that it's ignoring the -> operator?
Now, I don't need to use a PointerWrapper-esque class if there's a different way to do this, but it was all I could think of...
I can't modify Example either, but I can subclass it
You should provide Forwarder class - which redirects virtual calls to stored pointer. Freeing of forwarder class will not cause releasing of pointee. This approach does NOT need to do copy (which can be expensive/may be not implemented/or even not make sense):
struct Forwarder : Example
{
Example *impl;
Forwarder(Example *i) : impl(i) {}
void virtualfunction()
{
impl->virtualfunction();
}
};
Full code:
live demo:
#include <iostream>
#include <ostream>
using namespace std;
struct Example
{
virtual void virtualfunction()=0;
virtual ~Example() {}
};
struct Implmenetation : Example
{
bool alive;
Implmenetation() : alive(true) {}
void virtualfunction()
{
cout << "Implmenetation::virtualfunction alive=" << alive << endl;
}
~Implmenetation()
{
alive=false;
cout << "Implmenetation::~Implmenetation" << endl;
}
};
struct Forwarder : Example
{
Example *impl;
Forwarder(Example *i) : impl(i) {}
void virtualfunction()
{
impl->virtualfunction();
}
};
void codeIDontControl(Example *ex)
{
ex->virtualfunction();
delete ex;
}
void myCode()
{
Implmenetation impl;
codeIDontControl(new Forwarder(&impl));
//do something with ex //doesn't work because ex has been freed
impl.virtualfunction();
}
int main()
{
myCode();
}
Output is:
Implmenetation::virtualfunction alive=1
Implmenetation::virtualfunction alive=1
Implmenetation::~Implmenetation
It's bad design, really. Only the allocator should be allowed to free memory. Functions like this are dangerous, as they leave with with dangling pointers.
This is just off the top of my head, maybe you could try something like this? It's not a safe idea, but if someone implemented it I would be interested to know what happens.
class Foo
{
Foo(Foo* copy) : m_copy(copy) {}
~Foo() { if(m_copy) { *m_copy = *this; } } // Use copy constructor to create copy on destuction.
Foo* m_copy;
}
Foo copy(NULL);
Foo* original = new Foo(©);
MethodThatDeletes(original);
// Original should be destroyed, and made a copy in the process.
original = NULL;
// Copy should be a copy of the original at it's last know state.
copy;
You are providing a Example* to codeIDontControl. The overloaded operator-> on PointerWrapper is an for the PointerWrapper type not the Example* type or even the PointerWrapper* type (i.e. for a value or reference of that type not a pointer to that type).
Since the function you need to call isn't controlled by you, you will need to provide a complete wrapper of the type it expects as a wrapper over the instance you wish to control the lifetime of.
Sorry for the long title but I did want to be specific.
I expected the following code to work but it doesn't and I can't figure out why :/
#include <cstdio>
#include <cassert>
class UniquePointer
{
public:
void Dispose()
{
delete this;
}
friend void SafeDispose(UniquePointer*& p)
{
if (p != NULL)
{
p->Dispose();
p = NULL;
}
}
protected:
UniquePointer() { }
UniquePointer(const UniquePointer&) { }
virtual ~UniquePointer() { }
};
class Building : public UniquePointer
{
public:
Building()
: mType(0)
{}
void SetBuildingType(int type) { mType = type; }
int GetBuildingType() const { return mType; }
protected:
virtual ~Building() { }
int mType;
};
void Foo()
{
Building* b = new Building();
b->SetBuildingType(5);
int a = b->GetBuildingType();
SafeDispose(b); // error C2664: 'SafeDispose' : cannot convert parameter 1 from 'Building *' to 'UniquePointer *&'
b->Dispose();
}
int main(int argc, char* argv[])
{
Foo();
return 0;
}
Imagine it were legal. Then you could write code like this:
class Animal : public UniquePointer
{
};
void Transmogrify(UniquePointer*& p)
{
p = new Animal();
}
void Foo()
{
Building* b = nullptr;
Transmogrify(b);
b->SetBuildingType(0); // crash
}
Observe that you have violated the type system (you put an Animal where a Building should be) without requiring a cast or raising a compiler error.
I do not think that it is possible to make it work the way you have it designed. Instead, try the following:
template <typename T>
void SafeDispose(T * & p)
{
if (p != NULL)
{
p->Dispose();
p = NULL;
}
}
class UniquePointer
{
public:
void Dispose()
{
delete this;
}
protected:
UniquePointer() { }
UniquePointer(const UniquePointer&) { }
virtual ~UniquePointer() { }
};
It is not allowed because if it were you could do the following:
friend void SafeDispose(UniquePointer*& p)
{
p = new UniquePointer();
}
Building* building;
SafeDispose(building)
//building points to a UniquePointer not a Building.
I guess the work around would be a template function.
To answer the title of your question, you cannot bind a non-const reference to base to a derived class instance because you could then set that reference to a pointer to a base instance that isn't a derived. Consider this function:
void Renew(UniquePointer *& p) {
delete p;
p = new UniquePointer();
}
if you could pass it a pointer to Building you would be able to set it incorrectly to point to a UniquePointer instance.
As it has already been suggested the solution is to change your reference to a plain pointer. Not only this solves your problem, but it is also a better implementation of SafeDispose(); as you wrote it this function gave the false idea that you would always set to 0 all your UniquePointer instances. But what would happen if somebody wrote (assuming UniquePointer constructor was public for simplicity):
UniquePointer *p1 = new UniquePointer();
UniquePointer *p2 = p1;
SafeDispose(p1);
They would expect all of their UniquePointers to be properly taken care of, when p2 is actually invalid.
I guess your SafeDispose should probably look more like :
friend void SafeDispose(UniquePointer** p) ...
In order to invoke it using
SafeDispose(&(UniquePointer*)b);
Then it should work this way.
But your next statement
b->Dispose();
will break cause b should now be NULL, cause it has been disposed and set to NULL by your SafeDispose method.