1

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 | }
      | ^
Ingo Mi
  • 999
  • 12
  • 26
  • 3
    Your question is unclear. Whether or not a class member function returns a pointer has absolutely nothing to do, whatsoever, with "syntax for delete". If a class member returns a pointer it may or may not require a `delete` in order to avoid a memory leak. To figure it out you need to understand how memory allocation works in C++, and figure out how it should work for your program. Nothing more can be said until you [edit] your question and show something that meets all requirements for a [mre], as explained in the [help]. See [ask] for more information. – Sam Varshavchik Dec 01 '19 at 23:50
  • 1
    You need to show the code that's not working. We can't sit here and guess. – super Dec 02 '19 at 01:56
  • 1
    Your edited code still has some issues, for example with the constructor: 1) Remove the `*` in front of the declaration and definition of `*classname_c::classname_c`, constructors don't return values; 2) You're creating a new local variable `ptr` rather than using the class member, then discarding it on return resulting in a memory leak; 3) because you're not initializing the `ptr` member variable, the `delete[]` in the destructor is attempting to delete unknown memory. – jkb Dec 02 '19 at 21:50
  • 1
    @Ivanovich if one of the answers answered your question be sure not to forget to mark it as accepted so the question is marked as such – William Miller Dec 05 '19 at 01:51
  • @William yeah thanks for reminding me - done, thought I already did that - but was just an up vote. Still looking for "knowing what I am doing" in case of class member pointers. Searched through YouTube and made a tutorial list - also checking all the books I got for that topic but its a lot to cover and I don't want to just stay at "classes can be used as interfaces" :) How did you learned it if I may ask? Maybe I am overlooking some sources. – Ingo Mi Dec 05 '19 at 12:43
  • 1
    This kind of thing you mostly have to learn by doing, reading reference is useful but you don’t know what reference to look for unless you’re trying something specific and it’s not working (similar to how you came to this question), that being said you do need some foundation in the basics to even begin - I’d suggest finding a good introductory book and try to copy the examples and then modify them to see what works/is legal and what isn’t – William Miller Dec 05 '19 at 17:42

2 Answers2

2

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;
}
jkb
  • 2,376
  • 1
  • 9
  • 12
  • I completely rewrote my program but I still hang at the destructor because Bjarne Strousrup suggests always using a destructor to free the memory automatically. I edited the question as suggested to clarify it. Also still figuring out what is to much or not enough of a minimal reproducible example tho. Thanks upfront, really appreciate your help! – Ingo Mi Dec 02 '19 at 12:57
1

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);
William Miller
  • 9,839
  • 3
  • 25
  • 46
  • Thanks mate for editing the question, looks much better now. Actually that was what I am looking for. I guess i was a bit overwhelmed by the huge topic so thanks for clarifying. I completely rewrote my program but I still hang at the destructor because Bjarne Strousrup suggests always using a destructor to free the memory automatically. I edited the question as suggested to clarify it. Also still figuring out what is to much or not enough of a minimal reproducible example tho. Thanks upfront, really appreciate your help! – Ingo Mi Dec 02 '19 at 12:53
  • 1
    @Ivanovic Take a look at my edited answer, it has some more explanation of destruction and I believe an illustration of how to do what you are trying to do. *If* I'm understanding correctly that is. – William Miller Dec 02 '19 at 18:52