Home > Mobile >  Inconsistent behaviour c classes in classes
Inconsistent behaviour c classes in classes

Time:04-11

Edit based on the comments and the answer:

class Array {

public:
    int size;
    int *elements;

    explicit Array(int maxSize) : size(0), elements(new int[maxSize]) {}

    Array(Array &old) : elements(static_cast<int *>(malloc(sizeof(int) * size))), size(old.size) {
        memcpy(elements, old.elements, sizeof(int) * size);
    }

    Array(Array &&old) noexcept : size(old.size), elements(old.elements) {
        old.elements = nullptr;
    }

    ~Array() {
        delete[] elements;
    }

    void add(int e) {
        elements[size  ] = e;
    }
};
class Base {

public:
    Array a;

    explicit Base(Array &a) : a(std::move(a)) {}
};

int main() {

    Array a(5);
    a.add(1);
    std::cout << "Address: "<< a.elements << std::endl;
    std::cout << "First element: "<< a.elements[0] << std::endl;
    Array b = std::move(a);
    std::cout << "Address: "<< b.elements << std::endl;
    std::cout << "First element: "<< b.elements[0] << std::endl;
    Base c(b);
    std::cout << "Address: "<< c.a.elements << std::endl;
    std::cout << "First element: "<< c.a.elements[0] << std::endl;

    Base *d = static_cast<Base *>(malloc(sizeof(Base) * 2));
    Array e = std::move(c.a);
    std::cout << "Address: "<< e.elements << std::endl;
    std::cout << "First element: "<< e.elements[0] << std::endl;

    new (d) Base(e);
    std::cout << "Address: "<< d[0].a.elements << std::endl;
    std::cout << "First element: "<< d[0].a.elements[0] << std::endl;
}

I am trying to make some tailored structs and classes in c , and I am having some issues in copy constructors of classes.

What I am trying to do is to create a class in which a pointer is copied within the copy constructor and replaced with nullpointer in the previous object. Everything is fine until I try to do it inside another class.

In that case the first element of the array change value for no reason (I can explain).

Here is a mre:

class Array {

public:
    int *elements;
    int size;

    explicit Array(int maxSize) : size(0), elements(static_cast<int *>(malloc(sizeof(int) * maxSize))) {}

    Array(Array &old) : size(old.size), elements(old.elements) {
        old.elements = nullptr;
    }

    ~Array() {
        delete elements;
    }

    void add(int e) {
        elements[size  ] = e;
    }
};
class Base {

public:
    Array a;

    explicit Base(Array &a) : a(a) {}
};
int main() {
    Array a(5);
    a.add(1);
    std::cout << "Address: "<< a.elements << std::endl;
    std::cout << "First element: "<< a.elements[0] << std::endl;
    Array b = a;
    std::cout << std::endl << "Old address: "<< a.elements << std::endl;
    std::cout << "Address: "<< b.elements << std::endl;
    std::cout << "First element: "<< b.elements[0] << std::endl;
    Base c(b);
    std::cout << std::endl << "Old address: "<< b.elements << std::endl;
    std::cout << "Address: "<< c.a.elements << std::endl;
    std::cout << "First element: "<< c.a.elements[0] << std::endl;
    Base *d = static_cast<Base *>(malloc(sizeof(Base) * 2));
    Array e = c.a;
    std::cout << std::endl << "Old address: "<< c.a.elements << std::endl;
    std::cout << "Address: "<< e.elements << std::endl;
    std::cout << "First element: "<< e.elements[0] << std::endl;
    d[0] = Base(e);
    std::cout << std::endl << "Old address: "<< c.a.elements << std::endl;
    std::cout << "Address: "<< d[0].a.elements << std::endl;
    std::cout << "First element: "<< d[0].a.elements[0] << std::endl;
}

Output:

Address: 0x560838558eb0
First element: 1

Old address: 0
Address: 0x560838558eb0
First element: 1

Old address: 0
Address: 0x560838558eb0
First element: 1

Old address: 0
Address: 0x560838558eb0
First element: 1

Old address: 0
Address: 0x560838558eb0
First element: 1619232088

Process finished with exit code 0

CodePudding user response:

Your d object does not hold a valid array of Base objects. You merely allocated memory that may or may not be sufficient. But you never instantiated an object of type Base. So you cannot expect to use it.

If you need an old style array, just create it:

Base d[2] = {/*initialisation*/};

or use new if you need it on the free store. Usually, if you use malloc or its counterpart free in C , you are likely doing something wrong.

Also, and not directly related, have a look at std::exchange.

  •  Tags:  
  • c
  • Related