1

I've got a background in C and am trying to get my head around C++ classes and how the destructors get called as objects leave scope. As a side note, given the nature of what I am trying to do, I would rather not use STL structures like std::array<> or std::vector<> for the data containers I present below.

Here's a high level overview of my understanding. Given some class:

class some_class{
    public:
        int * member;
        size_t n_members;

        some_class(size_t count) ...
        ~some_class() ...

        // a member function or operator overload
        // that returns an instance of some_class
        some_class do_something()
}

...

some_class * container;
// Some scope
{
    some_class foo = some_class();
    some_class * bar = new some_class();
    container[0] = bar;
}

When some_class foo leaves the scope, its destructor gets called. If I wanted to store a pointer to an instance of some_class into container outside of the scope, I need to instantiate some_class bar on the heap so that memory does not immediately get de-allocated upon leaving scope - just like I would in C.

Now, the purpose of some_class is to hold an arbitrarily large amount of data and so int * member needs to be allocated on the heap.

Given above, the constructor and destructor for some_class() will look something like this:

// some_class constructor
some_class::some_class(size_t count) : n_members(count){
    member = new int[count];
}

// some_class destructor
some_class::~some_class(){
    delete[] member;
}

Now my problem becomes apparent: If I need to add an instance of some_class returned from the do_something() method, I am guaranteed to have a memory error (in this case, a double-free) because do_something() returns a stack-allocated some_class:

some_class * container = new some_class[n];
// Some scope
{
    some_class foo = some_class();
    some_class bar = foo.do_something();
    container[0] = &bar; // <-- I know this is stupid but that's the point of this question
}
delete[] container;

My way around this is to make foo.do_something() return a pointer to an instance of some_class. Of course, not a solution. How would one properly address such a situation in true C++ way?

For example, one thing I've been reading up on was the use of shared pointers or unique pointers (or smart pointers in general). However, my understanding is that using these pointers requires you to have instantiated your object in the heap. It also really doesn't help the whole issue about requiring foo.do_something() to return a pointer.

Anyways, any thoughts would be appreciated.

fpes
  • 964
  • 11
  • 22
  • *If I need to add an instance of some_class returned from the do_something() method, I am guaranteed to have a memory error* Yes. See [The Rule of Three](http://stackoverflow.com/questions/4172722/what-is-the-rule-of-three) to address that. – R Sahu May 07 '16 at 04:50
  • And then: http://stackoverflow.com/questions/4782757/rule-of-three-becomes-rule-of-five-with-c11/4782927#4782927 – Benjamin Lindley May 07 '16 at 04:52
  • 1
    `As a side note, given the nature of what I am trying to do, I would rather not use STL structures` Why. Given you are not a C++ expert you may be under some misconception that we can correct. – Martin York May 07 '16 at 06:11
  • @LokiAstari - The short is: I'm trying to maintain control of data access patterns that would be abstracted away by such structures. If I were building some sort of application, I would say go for it because it's easy. But for me, to understand how it works is more important than how to use it. – fpes May 07 '16 at 06:18
  • @FrancoSolleza: Both of these structures boil down to simply using pointers to access memory blocks (one stack one dynamic). They are a very very thin wrapper around a pointer. You can absolutely control when memory is allocated so these structures would solve your problems. – Martin York May 07 '16 at 06:49

2 Answers2

0

Smart pointer can be used to hold pointer inside some_class like this:

#include <memory>

class some_class{
  public:
    // smart pointer instead of raw pointer
    std::unique_ptr<int[]> member;
    size_t n_members;

    some_class(size_t count = 0) : member(new int[count]), n_members(count) {}

    // destructor not needed

    // a member function or operator overload
    // that returns an instance of some_class
    some_class do_something();
};

int main()
{
  int n = 3;
  // smart pointer instead of raw pointer
  std::unique_ptr<some_class[]> container(new some_class[n]);
  {
    some_class foo = some_class(10);
    some_class bar = foo.do_something();
    // use std::move to transfer pointer ownership
    container[0] = std::move(bar);
  }
  // no need to delete
}
user1887915
  • 1,299
  • 10
  • 13
-4

I used to be proficient in C++, but moved to Java long ago and my C++ is rusty now :(.

One thing you can do is create a constructor that accepts a member of the class. Inside it, just copy the properties to your new instance. (Also it is possible to make it with a static method instead of overloading the constructor).

some_class::some_class(some_class* obj){
    member = obj->member;
    n_members = obj->n_members;
}

So you can do this in your code:

some_class * container;
// Some scope
{
    some_class foo = some_class();
    some_class * bar = new some_class();
    container = new some_class(bar);
}

Hope it works for you.

mhyst
  • 297
  • 1
  • 7
  • Yes, your C++ is quite rusty. If all you do in your copy constructor is a member-wise copy, you haven't helped the situation at all, since that's precisely the copy constructor which the compiler will generate automatically, and it won't work correctly for a class like this. Also, it needs to take the object by reference, because taking an object by value requires a copy constructor. – Benjamin Lindley May 07 '16 at 05:07
  • How about playing with SP, BP? It would solve the problem, but I'm not sure how C++ like is it. – mhyst May 07 '16 at 05:28
  • Yes, I forgot the * and the ->, ->. But in result, your downvotes will make this the last time I attempt to answer a C++ question. – mhyst May 07 '16 at 05:33