- Expert C++
- Vardan Grigoryan Shunguang Wu
- 591字
- 2021-06-24 16:33:58
The heap
We described the stack as a manager of variables with automatic storage duration. The word automatic suggests that programmers shouldn't care about the actual memory allocation and deallocation. Automatic storage duration could be achieved only if the size of data or a collection of the data is known beforehand. This way, the compiler is aware of the number and type of function arguments and local variables. At this point, it seems more than fine, but programs tend to work with dynamic data— data of an unknown size. We will study dynamic memory management in detail in Chapter 5, Memory Management and Smart Pointers; for now, let's look at a simplified diagram of memory segments and find out what the heap is used for:
The program uses the heap segment in order to request more memory space than has been required before. This is done at runtime, which means the memory is being allocated dynamically during the program execution. The program requests the OS for new memory space whenever required. The OS doesn't actually know whether the memory is required for an integer, or for a user-defined Point, or even for an array of user-defined Point. The program requests the memory by passing the actual size of bytes that it requires. For example, to request a space for an object of type Point, the malloc() function can be used as follows:
#include <cstdlib>
struct Point {
float x;
float y;
};
int main() {
std::malloc(sizeof(Point));
}
The malloc() function allocates a contiguous memory space of sizeof(Point) bytes— let's say 8 bytes. It then returns the address of the first byte of that memory as it is the only way to provide access to space. And the thing is, malloc() doesn't actually know whether we requested memory space for a Point object or an int, and it simply returns void*. void* stores the address of the first byte of allocated memory, but it definitely cannot be used to fetch the actual data by dereferencing the pointer simply because void does not define the size of the data. Take a look at the following diagram; it shows that malloc allocates memory on the heap:
To actually use the memory space, we need to cast the void pointer to the desired type:
void* raw = std::malloc(sizeof(Point));
Point* p = static_cast<Point*>(raw);
Or, simply declare and initialize the pointer with a cast result:
Point* p = static_cast<Point*>(std::malloc(sizeof(Point)));
C++ solves this headache by introducing the new operator, which automatically fetches the size of the memory space to be allocated and converts the result to the desired type:
Point* p = new Point;
What happens when we access the members of the Point object pointed to by p? Dereferencing p returns the full Point object, so to change the value of member x, we should do the following:
(*p).x = 0.24;
Or, better still, access it with the arrow operator:
p->x = 0.24;
We will dive into the user-defined types and structs in particular in Chapter 3, Details of Object-Oriented Programming.
- 零基礎搭建量化投資系統:以Python為工具
- 解構產品經理:互聯網產品策劃入門寶典
- TypeScript Blueprints
- 計算機圖形學編程(使用OpenGL和C++)(第2版)
- Python機器學習:手把手教你掌握150個精彩案例(微課視頻版)
- 小學生C++創意編程(視頻教學版)
- 可解釋機器學習:模型、方法與實踐
- ExtJS高級程序設計
- TMS320LF240x芯片原理、設計及應用
- 編寫高質量代碼:改善Objective-C程序的61個建議
- Python開發基礎
- 算法設計與分析:基于C++編程語言的描述
- SQL Server實例教程(2008版)
- C語言程序設計教程
- Mastering PostgreSQL 11(Second Edition)