Last active
March 7, 2016 05:29
-
-
Save andrewrk/b2f363a413d82b5a3d90 to your computer and use it in GitHub Desktop.
create and destroy working in C++ without libstdc++
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <stdlib.h> | |
#include <stdio.h> | |
#include <stdarg.h> | |
#include <new> | |
// compile and run: | |
// g++ -std=c++11 -nodefaultlibs -fno-exceptions -fno-rtti -o test.o -c test.cpp && gcc -o test test.o && ./test | |
static void panic(const char *format, ...) __attribute__ ((noreturn)) __attribute__ ((format (printf, 1, 2))); | |
static void panic(const char *format, ...) { | |
va_list ap; | |
va_start(ap, format); | |
vfprintf(stderr, format, ap); | |
fprintf(stderr, "\n"); | |
va_end(ap); | |
abort(); | |
} | |
// It's safe to use stdlib free() to free the ptr returned by allocate(). | |
// however, since allocated memory created with create() must be freed with | |
// destroy(), you might consider always using destroy() to free memory for | |
// consistency's sake. I have verified that calling the constructor and | |
// destructor of a primitive type does nothing, and generated code using | |
// create()/destroy() for primitive types is identical to generated code using | |
// allocate()/free() | |
template<typename T> | |
static inline T *allocate(size_t count) { | |
T *ptr = reinterpret_cast<T*>(malloc(count * sizeof(T))); | |
if (!ptr) | |
panic("allocate: out of memory"); | |
return ptr; | |
} | |
// allocates enough memory for T and then calls the constructor of T. | |
// use destroy() to free the memory when done. | |
template<typename T, typename... Args> | |
static inline T *create(Args... args) { | |
T *ptr = allocate<T>(1); | |
new (ptr) T(args...); | |
return ptr; | |
} | |
// calls the destructor of T and then frees the memory | |
template<typename T> | |
static inline void destroy(T *ptr) { | |
ptr->T::~T(); | |
free(ptr); | |
} | |
class Foo { | |
public: | |
Foo(int x, const char *str) : xyz(x) { fprintf(stderr, "constructor %d %s\n", x, str); } | |
~Foo() { fprintf(stderr, "destructor\n"); } | |
void bar() { fprintf(stderr, "bar %d\n", xyz); } | |
private: | |
int xyz; | |
}; | |
int main(int argc, char *argv[]) { | |
Foo *foo = create<Foo>(19, "baz"); | |
foo->bar(); | |
destroy(foo); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment