#include <iostream>
using namespace std;
class temp
{
public:
temp()
{
std::cout << "Constructor created." << std::endl;
}
~temp()
{
std::cout << "Deconstructor called." << std::endl;
}
};
class scopedptr
{
private:
temp* ptr;
public:
scopedptr(temp* p)
{
ptr = p;
std::cout << "scoped" << std::endl;
}
~scopedptr()
{
delete ptr;
}
};
int main()
{
{
scopedptr a = new temp();
}
}
Most of the code above is not relevant but I wrote it so that there is a background to my question.
My question resides inside the main function, I know the line "scopedptr a = new temp();" will work, my doubt is the what is happening with the object a, is it associated with the class scopedptr or the temp class.
This code does not have many variables but what if there are multiple variables inside both the classes, will object a be able to call methods from class scopedptr or class temp or both.
I'm literally confused, what's happening with the object? which class is its type???
In the line
scopedptr a = new temp();
type of a is explicitly specified as scopedptr. Any usage of a must correspond to the type scopedptr.
When in doubt, simplify.
temp* temp_ptr = new temp();
scopedptr a{temp_ptr};
Then, there is less scope for confusion.
a is a scopedptr with an owning pointer to a temp.
will object a be able to call methods from class scopedptr or class temp or both
To be able to treat it as a smart pointer, you'd usually add member functions, deferencing the owned pointer:
class scopedptr {
public:
temp* operator->() { return ptr; }
temp& operator*() { return *ptr; }
};
You can now do a->func(); to call a function in the temp object.
Also look into the Rule of 5 for safe handling of the owned pointer.
Demo
Related
In the main function in this code what does this (ScopedPtr ent = new Entity()) mean
Why we are not using (ScopedPtr*) as per C++ instantiating style
#include<iostream>
#include<string>
class Entity
{
public:
Entity()
{
std::cout << "Created Entity!" << std::endl;
}
void Print()
{
std::cout << "Print" << std::endl;
}
};
class ScopedPtr
{
private:
Entity* m_Ptr;
public:
ScopedPtr( Entity* ptr)
: m_Ptr(ptr)
{}
/*ScopedPtr()
{
std::cout << "Hello";
}*/
~ScopedPtr()
{
std::cout << "Deleted Pointer";
delete m_Ptr;
}
};
int main()
{
{
ScopedPtr ent = new Entity();
}
std::cin.get();
}
And why the ScopedPtr(Entity Constructor) Didn't take a Entity* parameter and the code ran successfully.
ScopedPtr ent = new Entity();
The right-hand-side is a value of type Entity*, regardless of the details. So it could be written as
Entity* t = new Entity(); // doesn't matter what it's = to, just note its type.
ScopedPtr ent = t;
Now you have a variable definition T x = y; where y is not of type T. So, it implicitly converts to the correct type, and this is really
ScopedPtr ent = ScopedPtr(t);
The = here is initialization not assignment, so ent is initialized with that (converted) right-hand-side.
Why we are not using (ScopedPtr*) as per C++ instantiating style
Because new is not required to create objects. The whole point of ScopedPtr is to tie the lifetime of an object with dynamic storage duration ("on the heap") to another with automatic storage duration ("on the stack")
I am at the point learning classes/destructors in c++ and the need to return a pointer from a class member:
size_t * classname :: function();
but it doesn't work.
My logic is to declare a class variable e.g. classname * p_p = classfunction(data); that should access the class member:
size_t * classname :: classfunction(data)
{
//... do something ...
new p_p;
return p_p;
}
So the pointer address in theory gets returned to the main() variable p_p each time the member function of the class gets called.
Or should but doesn't and the program crashes somehow but not even sure on which point.
There is no compiler warning or error and the
debugger doesn't stops anywhere and I find nothing on returning a pointer from a class member function at all nor that it isn't allowed or something.
Also if there IS a syntax to return a pointer from a class member function I would need to have a syntax for delete the "new p_p".
So my question is: Should it work and how would I get this running or why is that maybe it is not working or forbidden? In my logic it should be a proper way but I may be wrong somehow and classes doesn't support this function completely.
EDIT:
Thanks to your answers and comments I got the pointer returned from the class member. (Also changed size_t to int since its just a pointer.) Like you suggested in the comments I added a minimal reproducible example:
#include <iostream>
using namespace std;
//########## class without ~ destructor ##########
class classname
{
public:
int *ptr;
int *classfunction(int);
void delete_classfunction(int*);
};
void classname::delete_classfunction(int*ptr)
{
delete[] ptr;
ptr = nullptr;
}
int *classname :: classfunction(int value)
{
int* ptr = new int[value]; //no delete?
ptr[0] = 5;
return ptr;
}
//########## class with ~destructor ##########
class classname_c
{
public:
int *ptr;
int value;
*classname_c(int );
void print(int*);
~classname_c();
};
void classname_c::print(int* ptr)
{
cout << ptr[0] << " shows value" << endl;
}
*classname_c::classname_c(int value)
{
int* ptr = new int[value];
ptr[0] = value;
} /*Brings warning: control reaches end of non-void function [-Wreturn-type]
48 | }
| ^*/
classname_c::~classname_c ()
{
cout << ptr[0] << endl;
delete[] ptr;
ptr = nullptr;
cout << ptr[0] << endl;
}
int main()
{ //class and deleting it myself calling the function delte
int value = 3;
int *ptr;
classname call;
ptr = call.classfunction(value); //create new ptr
cout << ptr[0] << " shows value" << endl;
call.delete_classfunction(ptr); //free memory
cout << ptr[0] << " shows value succ. deleted" << endl;
//class with destructor
classname_c dest(value);
dest.print(ptr);
cout << ptr[0] << " shows value succ. deleted" << endl; //its not!
return 0;
}
brings the following output:
5 shows value
0 shows value succ. deleted //How it should be
3 shows value
3 shows value succ. deleted //but its not, why? What did I do wrong?
Press <RETURN> to close this window...
Now I am not sure if/when the ~destructor is working or how I can test if I created the destructor right, because the ptr value is not deleted.
Also can I fix the
warning: control reaches end of non-void function [-Wreturn-type]
48 | }
| ^
It is perfectly fine to return a pointer from a member function, although returning a pointer to an allocated size_t seem a bit overkill.
What you want is probably something like this:
#include <iostream>
class cls
{
public:
size_t *ptr_func();
};
size_t *cls::ptr_func()
{
size_t *p = new size_t(42);
return p;
}
int main()
{
cls c;
size_t *p = c.ptr_func();
std::cout << (void *)p << '\n';
std::cout << *p;
delete p;
}
This may not answer your question but it might illustrate why this is not working how you expect. When you call a member function of a class, i.e. classname::function(), you need to have an instance of that class on which to call it. Something which has been defined like
class classname {
public:
classname() {ptr = new int(0);}
size_t* function();
~classname();
int* ptr;
};
size_t* classname::classfunction() {
size_t* ptr = new size_t();
return ptr;
}
Cannot be called by
classname * p_p = classfunction();
because classfunction() is not being called on an instance of classname and because classname is not size_t so you can't assign classname to the return from a function which returns type size_t unless a cast from one to the other has been explicitly defined (same goes for classname* and size_t*). You can do something like this
classname cls;
size_t* ptr = cls.classfunction();
Also note that destructors are not used for member functions, only for classes, so the syntax ~size_t*class::function() doesn't really make sense.
If you are trying to get a pointer to a class instance you can simply do
classname * ptr = new classname();
and put your //... do something ... in a constructor.
Edit
The use of a destructor is to perform the
[...] necessary cleanup needed by a class when its lifetime ends.
This means that the destructor is called when the instance of said class goes out of scope or is manually deleted. So when you have a class defined as above, with the destructor
classname::~classname() {
delete ptr;
}
This means that ptr will be deleted when the instance of classname reaches the end of its "lifetime". E.g.
int main() {
classname* cls = new classname();
// cls->ptr == int(0)
delete cls; // Calls ~classname()
// cls->ptr == NULL
}
The same is true for stack allocation (classname cls();) and in either case the destructor would be called automatically at the end of main (if that instance had not already been manually deleted).
Now what you can't do is delete a pointer that was allocated outside the class instance - if you want to be able to control a pointer like that while still having it accessible from outside the class you can make it a public member, as I did in the edited class declaration. This allows you to access the pointer from outside the class and then still delete it with the destructor,
int main() {
classname* cls = new classname();
// cls->ptr == 0
cls->ptr = 3;
// cls->ptr == 3
delete cls;
// cls->ptr == NULL
}
Hopefully that offers some clarity.
The warning is because of the constructor
*classname_c::classname_c(int value) {//...}
.... don't do this until you really know what you're doing, if you want a pointer to an instance of the class the constructor should be
classname_c::classname_c(int value) {//...}
and you should create the instance with
classname_c* cls = new classname_c(value);
can you please explain me why this code shows nothing except for the last std::cout line in main()? Checked through similar threads on stackoverflow.com, was not able to connect them to mine, is this pointing legal at all? I try to set a function pointer of a class to another class function:
#include <iostream>
class container;
class one {
public:
one()
{
eventsHandler = NULL;
};
~one() {};
void (container::*eventsHandler)();
};
class container {
public:
container()
{
zone = new one;
zone->eventsHandler = &container::events;
};
~container()
{
delete zone;
};
one *zone;
void events()
{
std::cout << "event handler is on..." << std::endl;
};
};
int main()
{
container *test = new container;
test->zone->eventsHandler;
std::cout << "just checker..." << std::endl;
delete test;
system("pause");
};
You should use operator->* for calling the member function pointer, and assign test as the object which will be called on,
(test->*test->zone->eventsHandler)();
or more clear,
(test->*(test->zone->eventsHandler))();
LIVE
You need to provide an object to call a pointer to memeber function:
container *test = new container;
(test->*test->zone->eventsHandler)();
Here, test is the object, test->zone->eventsHandler is the pointer to member function that you have saved, and operator->* joins them.
So, it is very much like any other member function; however, you can switch which objects to call a member on:
container *first = new container;
container *second = new container;
(first->*second->zone->eventsHandler)();
// both pointers point to the same function
std::cout << (first->zone->eventsHandler == second->zone->eventsHandler) << std::endl;
You have to actually call the function pointer, in line 38, as:
(test->*test->zone->eventsHandler)();
So I have 2 functions and 1 class.
with 1 function I want to Set value's of the integers stored in a class.
with the other function I want to use these value's again.
I'm using pointers as I thought this would be saved on Memory address's across the whole program.
#include <iostream>
using namespace std;
void Function1();
void Function2();
class TestClass
{
public:
TestClass();
~TestClass();
void SetValue(int localValue)
{
*value = localvalue;
}
int GetValue()const
{
return *value;
}
private:
*value;
};
TestClass::TestClass()
{
value = new int(0);
}
TestClass:
~TestClass()
{
delete value;
}
int main()
{
TestClass *tommy = new TestClass; //this didn't work,
//couldn't use SetValue or Getvalue in functions
Function1();
Function2();
return 0;
}
void Function1()
{
int randomvalue = 2;
TestClass *tommy = new TestClass; //because it didnt work in main, i've put it here
tommy->SetValue(randomvalue);
}
void Function2()
{
TestClass *tommy = new TestClass;
cout << tommy->GetValue();
<< endl; //this gave a error, so I put the above in again
//but this returns 0, so the value isn't changed
}
So, got a solution for me? I didn't got any compile errors, but the value isn't changed, probably because the destructor is called after Function1 has been completed. so how do I do it?
You need to pass your tommy from main() to each of your functions, not create a new one in each time, otherwise you're just losing the new Testclass objects you're creating in your functions, and actually here getting memory leaks because you use new.
Something like:
void Function1(TestClass * tommy) {
int randomvalue =2;
tommy->SetValue(randomvalue);
}
and then in main():
int main() {
TestClass *tommy = new TestClass;
Function1(tommy);
std::cout << tommy->GetValue() << std::endl; // Outputs 2
delete tommy;
return 0;
}
This is an odd use case, though - this would be the kind of thing you'd expect member functions to do. This would be better:
int main() {
TestClass *tommy = new TestClass;
tommy->SetValue(2);
std::cout << tommy->GetValue() << std::endl; // Outputs 2
delete tommy;
return 0;
}
without the need for Function1() and Function2(). Either way, you're going to have to fix:
private:
*value;
in your class, as someone else pointed out.
you are not passing your TestClass to either function so they functions can't see the tommy object you made. Then in each function you create a new local variable that just happens to have the same name as your local variable in main... They are all independent objects
Every time you write new TestClass, you are quite literally creating a new instance of a TestClass object. The new instance is not related to any existing instances in any way, except for being of the same type. To make the single instance of TestClass be "the one" being used by your functions, you need to pass it in as an argument to those functions.
Also -- Don't use pointers unless it is absolutely necessary.
Here's a cleaned up example of your code that accomplishes what it appears you were trying.
class TestClass
{
int value;
public:
TestClass() : value(0)
{}
int GetValue() const { return value; }
void SetValue(int x) { value = x; }
};
// takes a "reference", works somewhat like a pointer but with
// some additional safety guarantees (most likely will not be null)
// This will modify the original passed in TestClass instance.
void SetRandomValue(TestClass& tc)
{
int random = 2; // not really random...
tc.SetValue(random);
}
// take a const reference, similar to above comment, but a const
// reference cannot be modified in this scope
void Print(const TestClass& tc)
{
std::cout << tc.GetValue() << "\n";
}
int main()
{
// create a TestClass instance with automatic storage duration
// no need to use a pointer, or dynamic allocation
TestClass tc;
// Modify the instance (using reference)
SetRandomValue(tc);
// print the instance (using const reference)
Print(tc);
return 0;
}
I have a class. When this class is instantiated, I want the instance added to a list. When the object is deleted, I want it removed from the list.
So I give the object a shared pointer to itself. I then have a list of weak pointers to those shared pointers. When an object is created, it creates a shared pointer to itself, makes a weak pointer to that, and puts the weak pointer in a list.
When the object is destroyed, the shared pointer is as well. Whenever I try to access a member in the list, I ensure that it hasn't expired and that its use count isn't 0. Despite this, I still crash when the list member is destroyed. Why? Can I get around it? Here's my SSCCE:
#include <iostream>
#include <memory>
#include <vector>
class test
{
private:
std::shared_ptr<test> self;
public:
int val;
test(int set);
test(test ©) = delete; // making sure there weren't issues
// with a wrong instance being deleted
};
std::vector<std::weak_ptr<test>> tests;
test::test(int set):
val(set)
{
this->self = std::shared_ptr<test>(this);
tests.push_back(std::weak_ptr<test>(this->self));
}
void printTests()
{
for (auto i = tests.begin(); i != tests.end(); i++)
{
if (i->use_count() == 0 || i->expired())
{
tests.erase(i);
continue;
}
std::cout << i->lock()->val << std::endl;
}
std::cout << std::endl;
}
int main(int argc, char **argv)
{
{
test t(3);
std::cout << "First tests printing: " << std::endl;
printTests();
} // SEGFAULTS HERE
std::cout << "Second tests printing: " << std::endl;
printTests();
return 0;
}
The output of this program is as follows:
First tests printing:
3
Segmentation fault (core dumped)
Your issue is with how you are creating the self pointer:
this->self = std::shared_ptr<test>(this);
When a shared_ptr is created with this constructor, according to the documentation,
When T is not an array type, constructs a shared_ptr that owns the pointer p.
...
p must be a pointer to an object that was allocated via a C++ new expression or be 0
So the issue is that the shared_ptr is taking ownership of your stack object, so when the object gets destructed (and the shared_ptr along with it), shared_ptr is trying to delete your object that is on the stack. This is not valid.
For your use case, if you expect tests to outlive your vector, then you might be able to just store this.
I think the OP is interested in a solution to his original problem even if it uses a different method than the one he attempted. Here is a simple example of how to add an object to a global list when it is constructed, and remove it when it is deleted. One thing to remember: you must call AddList in every constructor you add to your base class. I didn't know whether you want the list to be accessible outside the class or not, so I added getter functions to return non-const iterators to the list.
class MyClass
{
private:
static std::list<MyClass*> mylist;
std::list<MyClass*>::iterator mylink;
// disable copy constructor and assignment operator
MyClass(const MyClass& other);
MyClass& operator = (const MyClass& other);
void AddList()
{
mylink = mylist.insert(mylist.end(), this);
}
void RemoveList()
{
mylist.erase(mylink);
}
public:
MyClass()
{
AddList();
}
virtual ~MyClass()
{
RemoveList();
}
static std::list<MyClass*>::iterator GetAllObjects_Begin()
{
return mylist.begin();
}
static std::list<MyClass*>::iterator GetAllObjects_End()
{
return mylist.end();
}
virtual std::string ToString() const
{
return "MyClass";
}
};
class Derived : public MyClass
{
virtual std::string ToString() const
{
return "Derived";
}
};
std::list<MyClass*> MyClass::mylist;
int main()
{
std::vector<MyClass*> objects;
objects.push_back(new MyClass);
objects.push_back(new MyClass);
objects.push_back(new Derived);
objects.push_back(new MyClass);
for (std::list<MyClass*>::const_iterator it = MyClass::GetAllObjects_Begin(), end_it = MyClass::GetAllObjects_End(); it != end_it; ++it)
{
const MyClass& obj = **it;
std::cout << obj.ToString() << "\n";
}
while (! objects.empty())
{
delete objects.back();
objects.pop_back();
}
}
This line is trouble:
tests.erase(i);
An iterator pointing to the erased element is invalid, and you can't increment it any longer. Luckily, erase returns a new iterator you can use:
auto i = tests.begin();
while (i != tests.end())
{
if (i->use_count() == 0 || i->expired())
{
i = tests.erase(i);
}
else {
std::cout << i->lock()->val << std::endl;
++i;
}
}