官术网_书友最值得收藏!

Initialization and destruction

As shown previously, the creation of an object is a two-step process: memory allocation and initialization. Memory allocation is a result of an object declaration. C++ doesn't care about the initialization of variables; it allocates the memory (whether it is automatic or manual) and it's done. The actual initialization should be done by the programmer, which is why we have a constructor in the first place.

The same logic follows for the destructor. If we skip the declarations of the default constructor or destructor, the compiler should generate them implicitly, which it would also remove in case they are empty (to eliminate redundant calls to empty functions). The default constructor will not be generated by the compiler if any constructor with parameters is declared, including the copy constructor. We can force the compiler to implicitly generate the default constructor:

class Product {
public:
Product() = default;
// ...
};

We also can force it not to generate the compiler by using the delete specifier, as shown here:

class Product {
public:
Product() = delete;
// ...
};

This will prohibit default-initialized object declarations, that is, Product p; won't compile.

Destructors are called in the order opposite to object declarations because the automatic memory allocation is managed by a stack and the stack, is a data structure adapter that follows the  last in, first out ( LIFO) rule.

Object initialization happens on its creation. Destruction usually happens when the object is no longer accessible. The latter may be tricky when the object is allocated on the heap. Take a look at the following code; it declares four Product objects in different scopes and segments of memory:

static Product global_prod; // #1

Product* foo() {
Product* heap_prod = new Product(); // #4
heap_prod->name = "Sample";
return heap_prod;
}

int main() {
Product stack_prod; // #2
if (true) {
Product tmp; // #3
tmp.rating = 3;
}
stack_prod.price = 4.2;
foo();
}

global_prod has a static storage duration and is placed in the global/static section of the program; it is initialized before main() is called. When main() starts, stack_prod is allocated on the stack and will be destroyed when main() ends (the closing curly brace of the function is considered as its end). Though the conditional expression looks weird and too artificial, it's a good way to express the block scope.

The tmp object will also be allocated on the stack, but its storage duration is limited to the scope it has been declared in: it will be automatically destroyed when the execution leaves the if block. That's why variables on the stack have automatic storage duration. Finally, when the foo() function is called, it declares the heap_prod pointer, which points to the address of the Product object allocated on the heap.

The preceding code contains a memory leak because the heap_prod pointer (which itself has an automatic storage duration) will be destroyed when the execution reaches the end of foo(), while the object allocated on the heap won't be affected. Don't mix the pointer and the actual object it points to: the pointer just contains the value of the object, but it doesn't represent the object.

Don't forget to deallocate the memory that's dynamically allocated on the heap, either by manually calling the delete operator or using smart pointers. Smart pointers will be discussed in Chapter 5Memory Management and Smart Pointers.

When the function ends, the memory for its arguments and local variables allocated on the stack will be freed, but global_prod will be destroyed when the program ends, that is, after the main() function finishes. The destructor will be called when the object is about to be destroyed.

主站蜘蛛池模板: 德化县| 榆林市| 石首市| 遂宁市| 婺源县| 镇雄县| 青龙| 濉溪县| 郸城县| 斗六市| 邳州市| 阜阳市| 会东县| 扎赉特旗| 黄龙县| 陈巴尔虎旗| 宝兴县| 常宁市| 个旧市| 南投县| 湟中县| 永年县| 托里县| 碌曲县| 榕江县| 犍为县| 永丰县| 松溪县| 乌拉特前旗| 彰武县| 澄江县| 博兴县| 盐亭县| 沂水县| 兴隆县| 宜州市| 来安县| 泽普县| 平远县| 安平县| 许昌市|