C++20coreadvanced
Constexpr Dynamic Memory Allocation (C++20 Addition)
C++20 · The Big Four · Compiler flag: -std=c++20
Explanation
`new` and `delete` can be used in `constexpr` contexts for dynamic allocation.
Real-World Scenario
Allocate compile-time arrays in a configuration system.
Quick Snippet
snippet.cpp
constexpr int* alloc() { return new int[5]; }Full Example
constexpr_allocation.cpp
// CodeNebula - C++20 Example: Constexpr Allocation
// Compile: g++ -std=c++20 -Wall -Wextra -o example constexpr_allocation.cpp
// Demonstrates C++20 constexpr new/delete: transient allocation during
// constant evaluation. Memory must be freed before the constexpr context ends.
#include <iostream>
#include <memory>
#include <array>
// ------------------------------------------------------------------
// 1. constexpr function using new/delete (transient allocation)
// ------------------------------------------------------------------
constexpr int sum_with_buffer(int n) {
int* buffer = new int[n];
for (int i = 0; i < n; ++i)
buffer[i] = i + 1;
int total = 0;
for (int i = 0; i < n; ++i)
total += buffer[i];
delete[] buffer; // Must free before returning
return total;
}
// ------------------------------------------------------------------
// 2. constexpr dynamic array reversal
// ------------------------------------------------------------------
constexpr auto reverse_array(const int* input, int n) {
struct Result {
int data[10]{};
int size = 0;
};
int* temp = new int[n];
for (int i = 0; i < n; ++i)
temp[i] = input[n - 1 - i];
Result r;
r.size = n;
for (int i = 0; i < n; ++i)
r.data[i] = temp[i];
delete[] temp;
return r;
}
// ------------------------------------------------------------------
// 3. constexpr linked list with new/delete
// ------------------------------------------------------------------
struct Node {
int value;
Node* next;
};
constexpr int sum_linked_list(int n) {
// Build linked list: 1 -> 2 -> 3 -> ... -> n
Node* head = nullptr;
for (int i = n; i >= 1; --i) {
Node* node = new Node{i, head};
head = node;
}
// Sum all values
int total = 0;
Node* curr = head;
while (curr) {
total += curr->value;
curr = curr->next;
}
// Free all nodes
while (head) {
Node* temp = head;
head = head->next;
delete temp;
}
return total;
}
// ------------------------------------------------------------------
// 4. constexpr unique_ptr-like RAII wrapper
// ------------------------------------------------------------------
constexpr int demo_raii_allocation() {
// Use a simple scope-based pattern
int* p = new int(42);
int val = *p;
*p = val * 2;
int result = *p;
delete p;
return result;
}
// ------------------------------------------------------------------
// 5. constexpr sorting with dynamic buffer
// ------------------------------------------------------------------
constexpr auto sort_values(std::initializer_list<int> init) {
struct SortedResult {
int data[10]{};
int size = 0;
};
int n = static_cast<int>(init.size());
int* buf = new int[n];
int idx = 0;
for (int v : init)
buf[idx++] = v;
// Bubble sort
for (int i = 0; i < n - 1; ++i)
for (int j = 0; j < n - i - 1; ++j)
if (buf[j] > buf[j + 1]) {
int tmp = buf[j];
buf[j] = buf[j + 1];
buf[j + 1] = tmp;
}
SortedResult r;
r.size = n;
for (int i = 0; i < n; ++i)
r.data[i] = buf[i];
delete[] buf;
return r;
}
int main()
{
std::cout << "=== constexpr new/delete ===" << std::endl;
constexpr int s5 = sum_with_buffer(5); // 1+2+3+4+5
constexpr int s10 = sum_with_buffer(10); // 1+2+...+10
std::cout << " sum(1..5) = " << s5 << std::endl;
std::cout << " sum(1..10) = " << s10 << std::endl;
static_assert(s5 == 15);
static_assert(s10 == 55);
std::cout << "\n=== constexpr Dynamic Reversal ===" << std::endl;
constexpr int input[] = {10, 20, 30, 40, 50};
constexpr auto rev = reverse_array(input, 5);
std::cout << " Reversed:";
for (int i = 0; i < rev.size; ++i)
std::cout << " " << rev.data[i];
std::cout << std::endl;
std::cout << "\n=== constexpr Linked List ===" << std::endl;
constexpr int ll5 = sum_linked_list(5);
constexpr int ll100 = sum_linked_list(100);
std::cout << " Linked list sum(1..5) = " << ll5 << std::endl;
std::cout << " Linked list sum(1..100) = " << ll100 << std::endl;
static_assert(ll100 == 5050);
std::cout << "\n=== constexpr RAII-like ===" << std::endl;
constexpr int raii = demo_raii_allocation();
std::cout << " 42 * 2 = " << raii << std::endl;
std::cout << "\n=== constexpr Sort with Dynamic Buffer ===" << std::endl;
constexpr auto sorted = sort_values({9, 3, 7, 1, 5, 2, 8, 4, 6, 0});
std::cout << " Sorted:";
for (int i = 0; i < sorted.size; ++i)
std::cout << " " << sorted.data[i];
std::cout << std::endl;
std::cout << "\n All static_asserts passed" << std::endl;
return 0;
}
/*
Expected output:
=== constexpr new/delete ===
sum(1..5) = 15
sum(1..10) = 55
=== constexpr Dynamic Reversal ===
Reversed: 50 40 30 20 10
=== constexpr Linked List ===
Linked list sum(1..5) = 15
Linked list sum(1..100) = 5050
=== constexpr RAII-like ===
42 * 2 = 84
=== constexpr Sort with Dynamic Buffer ===
Sorted: 0 1 2 3 4 5 6 7 8 9
All static_asserts passed
*/
Run command
g++ -std=c++20 -Wall -Wextra -o example constexpr_allocation.cpp