I am trying to write a factory function that creates a constexpr object that uses new. Is this even possible?
The following code does not compile:
aa.cpp: In function ‘int main()’: aa.cpp:23:39: in ‘constexpr’ expansion of ‘((Buffer*)(& b))->Buffer::~Buffer()’ aa.cpp:10:36: error: deallocation of already deallocated storage 10 |
constexpr ~Buffer() { delete[] data; }
#include <random>
struct Buffer {
int size;
int* data;
constexpr Buffer(int n) : size(n), data(new int[n])
{
for (int i = 0; i < n; ++i) data[i] = i;
}
constexpr ~Buffer() { delete[] data; }
constexpr int get(int i) const { return data[i]; }
static constexpr Buffer Create(int n)
{
Buffer buf(n);
// ...
return buf;
}
};
constexpr void test(int d)
{
Buffer b2(d);
}
int main() {
constexpr Buffer b = Buffer::Create(4);
constexpr Buffer b2(43); // also does not compile: error: ‘Buffer(43)’ is not a constant expression because it refers to a result of ‘operator new’
test(rand()); // This is Ok
}
While constexpr does allow certain uses of operator new, it does not allow storing the result of operator new for use at runtime (more specifically, the new memory must be deleted in the same compile-time expression).
Think about it: how would a compile-time heap allocation be usable at runtime?
You can use heap allocations at compile-time only, or at runtime only. Not a mix of both for the same allocation.
Here is a valid example:
struct Buffer {
constexpr Buffer(int n)
{
int* data = new int[n];
for (int i = 0; i < n; ++i)
data[i] = i;
delete[] data;
}
};
You can't create a constexpr object that requires dynamically allocated memory. You can allocate memory in a constexpr context, but you must release it before the constexpr context ends.
As for test(rand()); // This is Ok, it's not actually executed at compile time. constexpr function is not guaranteed to be executed at compile time unless it's used to initialize a constexpr variable.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With