object creating in C/C++

construct an object

the compiler will define a default constructor with no parameters, if there is no user defined default constructors. usually the parameters for user defined(UD) default constructors should have default values.

directly call the UD constructor will create an object; call the UD through new keyword will create an object pointer.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
struct TreeNode{
int val;
TreeNode *right ;
TreeNode *left;
TreeNode(int x=0): val(x), left(NULL), right(NULL){}; //user defined constructor
TreeNode(const TreeNode *cp) //copy constructor
{
val = cp->val;
right = cp->right;
left = cp->left;
}
}
TreeNode node1;
TreeNode node2(100);
TreeNode *node_p = new TreeNode(10);

create an object in pure C

new operator do two things: allocate memory for a C++ class object, then call the object’s constructor to initialize this object. basically, new packages memory management of objects and objects initialization.

while in pure C, since there is no object constructor, after malloc memory for the structure, either call an initial function or manually initialize this structure member variables.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
TreeNode
{
int val;
TreeNode *right ;
TreeNode *left;
}
int main()
{
TreeNode *p = (TreeNode*) malloc( sizeof(struct TreeNode));
p->val = 0;
p->right = NULL;
p->left = NULL ;
}
```
## construct an object array
beyond creating one object (pointer), how to create object array.
```c
int nums = 5;
TreeNode tree_array[nums];
TreeNode *tree_p = (TreeNode*) new TreeNode[nums];

be aware, each element in tree_array has the whole memory of TreeNode structure; and tree_p++ will go to next TreeNode structure, tree_p[i] is also a whole memory of TreeNode structure.

create an object array in pure C

1
2
int nums = 5;
TreeNode *tree_p = (TreeNode*) malloc(nums * sizeof(TreeNode));

basically malloc will return a pointer to a block of memory, but it’s not responsible to initialize this block of memory.

the rule of five

rule of three is about how to manage dynamically allocated resources in C++.

why it is necessary?

1) when parameter B is copying by value from A, if no user defined copy constructor, the compiler will do a shallow copy from A to B by default, in which a new pointer point to the same content address. at the end of function call, the parameter B is out of scope, so destructor is called, and A is still there. but at the end of the main function, A is out of scope, need deallocating, then error is B already deallocate the content of A.

with a user defined copy constructor, B will get a deep copy of A, so no sharing content, no problems when deallocating either B or A.

2) if no user specified assignment constructor, a shallow copy happens, then error-potential. and assignment constructor (operator=) can be implemented with copy constructor.

1
2
3
4
5
6
7
int main()
{
TreeNode node1;
TreeNode node2 = node1; //actually a copy-construct, same as node2(node1)
TreeNode node3 ;
node3 = node1 ; //a compiler assignment-construct by default(shallow copy)
}