-1

I built a class which stores a buffer type, its size, and a pointer to that buffer. The intention is to access the buffer through that pointer to perform all the operations.
The issue is, when I assign an instance of this class to another like so:

    buffer = ExampleUsage(10);  

the pointer breaks.

Here are the two classes (buffer and a usage for that buffer):
First the buffer I use in my example:

    class ExampleBuffer {
    public:
        ExampleBuffer() :size(0), buffer(0) {}
        ExampleBuffer(size_t size) {
            this->size = size;
            buffer = vector<int>(size);
        }

        void Draw(int index, int val) {
            buffer[index] = val;
        }

        int Get(int index) {
            return buffer[index];
        }
    protected:
        int size;
        vector<int> buffer;
    };

Next the class I use to access the buffer and perform operations on it:

    class ExampleUsage {
    public:
        ExampleUsage() :
            size(0),
            buffer(0), 
            ptr(&buffer) {}

        ExampleUsage(int size) :
            size(size),
            buffer(size), 
            ptr(&buffer) {}

        void Draw(int index, int val) {
            ptr->Draw(index, val);
        }

        int Get(int index) {
            return ptr->Get(index);
        }
    protected:
        int size;
        ExampleBuffer buffer;
        ExampleBuffer* ptr;
    };

Here's a program to demonstrate the problem.

class SomeClass {
public:
    void Init() {
        buffer = ExampleUsage(10);
    }

    void DoStuff() {
        buffer.Draw(0, 1234);
    }

protected:
    ExampleUsage buffer;
};

int main() {
    SomeClass example;
    example.Init();
    example.DoStuff();
}

When it executes, it initializes ExampleUsage with its default constructor and then another instance is generated in the Init() method of SomeClass and assigned to buffer.
Then the method DoStuff() is called, which executes the buffer's Draw() method and from there, the pointer should access the stored ExampleBuffer but it points to a nullptr instead leading to an exception.

I know that if I remove the line:

    buffer = ExampleUsage(10);

and instead replace it with something like:

    buffer.Init(10); //hypothetical method to initialize the class.

it will work.

Why does the pointer in ExampleUsage not point to the ExampleBuffer in this program?

Renge
  • 438
  • 3
  • 14
  • Why are you going out of your way to make it work in such an odd way? People expect things to work with `new` or, in less common cases, factory methods, but calling something named `Init` is wildly out of place in most C++ code bases. – tadman May 17 '19 at 18:34
  • 2
    See this question about the [Rule of Three/Fiive](https://stackoverflow.com/questions/4782757/rule-of-three-becomes-rule-of-five-with-c11). You should implement (and use) a constructor for `SomeClass`, along with copy assignment, copy constructor, move assignment, and move constructors. – 1201ProgramAlarm May 17 '19 at 18:43
  • If you mean, the `Init` in `SomeClass`, it's just to demonstrate that the constructor wasn't used at that point. The init to replace the assignment at the end was to show a hypothetical way of how the error wouldn't occur. Neither of those were used in the implementation. – Renge May 17 '19 at 18:45

1 Answers1

2

In this code you are copying both the vector and the pointer:

buffer = ExampleUsage(10);

At the end of the day the buffer object has a valid copy of the vector plus the pointer to some memory where another vector was located recently.

class ExampleUsage {
    // ...
    ExampleBuffer buffer; // This is a valid copy of the object
    ExampleBuffer* ptr; // Where does this ptr point after the copying?
};

This is the reason to get an exception. Other questions regarding the code: Why do you store the size externally if you have this information as vector::size()? Why do you store both the vector and the pointer (preferring to use the pointer)?

Consider a simpler C++-idiomatic solution.

Dmitry Kuzminov
  • 4,427
  • 5
  • 12
  • 26
  • 1
    Thanks for the answer, that cleared it up for me. In the implementation it is a vector with width and height, so there would be a width and a height variable, leaving the size in, was an oversight. – Renge May 17 '19 at 18:46