- 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.
- JavaScript全程指南
- Azure IoT Development Cookbook
- Apache Kafka Quick Start Guide
- 單片機(jī)C語言程序設(shè)計實訓(xùn)100例
- SQL 經(jīng)典實例
- Django 3.0入門與實踐
- Python Machine Learning Blueprints:Intuitive data projects you can relate to
- 區(qū)塊鏈架構(gòu)之美:從比特幣、以太坊、超級賬本看區(qū)塊鏈架構(gòu)設(shè)計
- WildFly Cookbook
- Oracle Database XE 11gR2 Jump Start Guide
- Learning WordPress REST API
- 從零開始學(xué)算法:基于Python
- Java面試一戰(zhàn)到底(基礎(chǔ)卷)
- Mastering R for Quantitative Finance
- Illustrator CS6中文版應(yīng)用教程(第二版)