Search code examples
c++qtoopqsharedpointer

Objects creation and members declaration in C++


I come from a Java background and I recently started to learn Qt with C++. While doing some coding a few doubts about objects creation and members declaration have come to me:

Supposing I have a class declared as follows:

ClassA.h:

class ClassA {

private:
    MyObject myObj;
    QString *declaredArray;
    QSharedPointer<MyObject> obj;
public:
    void setInfo();
}

ClassA.cpp

void ClassA::setInfo() {
    declaredArray = new QString[5];
    obj = QSharedPointer<MyObject>(new MyObject, doDeleteLater);
}

What happened in the header where MyObject myObj; was declared? Was an object of type MyObject created in the stack and assigned to variable myObj using a constructor which takes no arguments? Or only an empty variable prepared to store a MyObject object was declared?

In ClassA.cpp how would I assign a new object created in the stack to myObj variable?

declaredArray is an array of ints created in the heap, should I add a destructor with a delete declaredArray; to avoid memory leaks?

What happened in the header where QSharedPointer<MyObject> obj; was declared? Was an empty pointer to MyObject created? Is the assignment in ClassA.cpp (obj = QSharedPointer<MyObject>(new MyObject, doDeleteLater);) correct?


Solution

  • There will be space for myObj (of the size of MyObject) wherever ClassA is allocated (if ClassA is allocated on the stack, space for myObj will be on the stack).

    If an applicable default constructor exists for MyObject, and either:

    1. You define an explicit default constructor as follows:
        ClassA() :
            myObj(),
            declaredArray(NULL),
            obj(NULL) { }
    
    1. You have no constructors declared, thus causing an implicitly-declared default constructor to be added by the compiler, which roughly resembles the above functionality.

    ... then myObj will be initialized to the default value (MyObject()).

    Also note that any heap-allocated memory you create with new should be deallocated with delete on destruction. Therefore, you should also have a destructor:

    ~ClassA() {
        if (delcaredArray != NULL) {
            delete[] declaredArray;
        }
    }
    

    Thanks to RAII, you won't need to destruct myObj and obj if explicitly initialized in the ClassA constructor. If they are not, however, then you will need to explicitly destruct them (e.g., in the case of the shared pointer, decrement the counter).


    To answer your other questions explicitly:

    What happened in the header where MyObject myObj; was declared? Was an object of type MyObject created in the stack and assigned to variable myObj using a constructor which takes no arguments? Or only an empty variable prepared to store a MyObject object was declared?

    myObj will only be default-constructed (constructed with a constructor that takes no arguments) if the default constructor exists and has been created (implicitly or explicitly).

    In ClassA.cpp how would I assign a new object created in the stack to myObj variable?

    If myObj was valid, then myObj = MyObject(...); (without a new keyword) would suffice. Note that this would call operator=() (the assignment operator) on myObj, so myObj needs to be already defined for this to be fully defined behavior. If it is already default constructed, then myObj = MyObject(...); is fine.

    declaredArray is an array of int’s created in the heap, should I add a destructor with a delete declaredArray; to avoid memory leaks?

    Yes, you should, as shown above.

    What happened in the header where QSharedPointer obj; was declared? Was an empty pointer to MyObject created? Is the assignment in ClassA.cpp (obj = QSharedPointer(new MyObject, doDeleteLater);) correct?

    The documentation for QSharedPointer shows that its default constructor is a QSharedPointer pointing to NULL. If you have a default constructor which is appropriately calling the default constructor for the members, then you should be fine.

    A properly constructed (e.g. default or non-default constructed, but initailized) QSharedPointer can be assigned to using the assignment operator as you showed: (obj = QShardPointer<MyObject>(new MyObject)).