It looks like you are approaching C ++ from a managed language such as C #. In C ++, everything is a little different.
What you describe as reference types does not exist in C ++. Types in C ++ are not "reference types" and are not "value types". They are just "types." Regardless of whether they are processed through references (or pointers) or by value, it completely depends on the code that uses the type (and not the type definition). In contrast, in languages like C #, a type declarator decides whether the type should be treated as a reference or value. C ++ has something called a link, but it has nothing to do with what you are describing. At the end, I mentioned references to C ++.
Now let's see if we can handle several parts of your question:
The pointer is pushed onto the stack, and the actual data that the pointer points to is created and pushed onto the heap.
May be. That would be true if you create such an object, for example:
class MyClass { }; ... MyClass* pObj1 = new MyClass(); MyClass* pObj2 = (MyClass*)malloc( sizeof(MyClass) );
But if you create the object as follows:
MyClass obj3;
In the latter case, the object is allocated on the stack and has no pointer or reference. You are manipulating it as a "value type".
MyClass *pObj3 = &obj3;
Now pObj3 is a pointer (on the stack) to obj3 , which is also on the stack. See? There is no connection between the definition of a class and where the objects of this class are stored. It depends on how you use this type. This is a fairly common combination of objects for both the stack and the heap of the same type.
The standard arrays and user-defined classes are refence types. Is it correct?
Not; Arrays are just a collection of objects of the same type / size located in consecutive memory cells. An array can be allocated on the stack or on the heap, as with separate objects.
C and C ++ do not put any separate semantics in arrays (with one exception, I will specify per second). Once they are selected, this is just a bunch of objects that happen sequentially. It is up to your program to use array operations or direct pointer operations to access individual members. It means:
arrayOfClass[i] exactly matches the expression ((Class*)*(array + i)) . In C, you can even say i[arrayOfClass] , which means that arrayOfClass[i] (C ++ will complain because it has more stringent type rules).- You can use array operators in pointers for objects that are not part of the array (and probably fail)
- You can use normal pointer operations on array elements.
- You can allocate a “large” chunk of memory and “create your own array” by interpreting smaller consecutive fragments of this memory as if they were members of an array of smaller objects (this is exactly what you get when you use malloc ()).
Arrays are not types in themselves; it's just a convenient way to select multiple objects and a way to make pointers that are more convenient in some cases.
The only exception that comes to my mind is the rule "arrays are not special" - these are case arrays allocated in C ++ via new . When you allocate an array through new , it leaves information (usually on the heap next to the array, but this is not necessary) about how many elements are contained in the array when it was allocated. Then, to delete the array, use the special delete [] operator. delete [] finds and uses this extra bit of information to properly delete all elements of the array.
Secondly, my main question is: do the c and C ++ memory management mechanisms (malloc, free and new, delete) always handle this correctly and free the memory pointed to by the class or array?
As long as you do everything right, yes.
Does everything work if these pointers are somehow reassigned to other objects of the same size / type on the heap?
Yes for free() , although using pointers to a different type when you call free () (other than void* ) is a rather unusual task. There is legitimate use of such things, but they are advanced topics. You might want your design to be developed by an experienced developer to make sure that it really fits.
delete is another matter; if you use a pointer to a type other than what is stored in the buffer when you delete , the behavior is "undefined" (aka you will most likely crash). This is because delete does more than free() does; it also calls the object's destructor method, and the compiler relies on the type of pointer to invoke the correct method. If you use the wrong type of pointer, the wrong method will be called and who knows what will happen. You can put something else in the buffer after new , but this may require a non-trivial amount of work, and again is an advanced topic.
Also note that you should never allocate malloc() and free with delete , and also not allocate with new and free with free() . Make sure your methods are paired properly.
What if the class has a pointing element pointing to another object? I suppose that removing / releasing a class object does not release what its pointer to an element points to, right?
In C ++, the canonical way to handle this is that the class must have a destructor, and the destructor will take care of freeing the pointer element. In C, you have no choice, and you need to clear the pointer element manually before clearing the external pointer.
Everything assumes that the object owns the contents indicated by the member pointer. In managed languages such as C #, all objects “belong” at runtime and are deleted under the control of the garbage collector, so you don’t have to worry about that. In C ++. who "owns" the objects specified in the member elements is determined by the semantics of your program, not the language, and you should pay attention to when it is time to delete the embedded objects. If you skip the right time to delete an object, you skip memory; if you delete it too soon, you will get undefined behavior and crashes (when some code tries to use an object that has already been deleted).
Now the C ++ link is basically a pointer with a little sugar coverage, designed to make it easier to use certain pointers. Basically, you can do almost nothing with links that you cannot do in C ++ simply by using pointers; a few exceptions are advanced topics that I will skip (I would have to consider it to give a theme of justice, and I have no resources).
For your point of view, a C ++ link is just a pointer that looks like a stack object.
CMyClass pObj1 = new CMyClass(); CMyClass& myObject = pObj1; // Create a reference to the object pointed by pObj1 pObj1->Method1(); // Use the pointer to call Method1 pObj1.Method1(); // Use the reference to call Method1
Given your level of knowledge in C ++, I can stay away from links for now, until you realize that memory management in C / C ++ is a bit better.