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

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.

主站蜘蛛池模板: 襄樊市| 肥东县| 济阳县| 西宁市| 乌海市| 嵊泗县| 枣强县| 古蔺县| 兖州市| 玉山县| 永清县| 万源市| 大石桥市| 睢宁县| 库车县| 孝感市| 邯郸市| 内江市| 正蓝旗| 民权县| 临夏县| 松原市| 故城县| 商都县| 新昌县| 北宁市| 江陵县| 县级市| 枞阳县| 开化县| 白山市| 义乌市| 科技| 视频| 玛曲县| 谷城县| 来凤县| 南通市| 惠安县| 辽宁省| 衡水市|