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

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.

主站蜘蛛池模板: 仙桃市| 玛纳斯县| 萝北县| 无为县| 墨竹工卡县| 五河县| 清原| 达日县| 昆明市| 平度市| 阿拉尔市| 南城县| 民乐县| 溧阳市| 惠东县| 乌苏市| 永新县| 建水县| 汪清县| 衡阳市| 金阳县| 达拉特旗| 彰武县| 肇州县| 富锦市| 绥化市| 松滋市| 兖州市| 蓝山县| 天柱县| 通江县| 永川市| 平乐县| 晋宁县| 鄂州市| 葫芦岛市| 大厂| 贵州省| 营口市| 彰化市| 长沙县|