- 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.
- Learning Microsoft Windows Server 2012 Dynamic Access Control
- Python自動化運維快速入門(第2版)
- Building a RESTful Web Service with Spring
- 精通搜索分析
- Oracle 12c中文版數據庫管理、應用與開發實踐教程 (清華電腦學堂)
- Functional Programming in JavaScript
- CouchDB and PHP Web Development Beginner’s Guide
- 自制編程語言
- Julia 1.0 Programming Complete Reference Guide
- 軟件項目管理實用教程
- C++程序設計
- JSP程序設計與案例實戰(慕課版)
- SQL Server 2012 數據庫應用教程(第3版)
- 輕松學Scratch 3.0 少兒編程(全彩)
- Learning Redux