gsl provides a random number generator that i use in my work. one has to allocate the random number generator at the start of the program and then deallocate the memory at the end of the program. c++11 provides smart pointers which keep track of the objects they point to for the purpose of memory management. when the smart pointer goes out of scope the resource is automatically deallocated when the associated object is destroyed. that’s one headache less for the programmer!
the following code demonstrates how one uses the gsl random number interface in a c-style code and compares it with the use of smart pointers to automatically manage resource deallocation for you.
#include <iostream>
#include <gsl/gsl_rng.h>
#include <memory> // header file for unique_ptr shared_ptr
// c-style usage
void c() {
gsl_rng *r = gsl_rng_alloc(gsl_rng_taus); // allocation
std::cout << gsl_rng_uniform(r) << std::endl;
gsl_rng_free(r); // de-allocation
}
// c++ style usage with shared_ptr
void cpp_shared() {
std::shared_ptr<gsl_rng> r(gsl_rng_alloc(gsl_rng_taus), gsl_rng_free);
std::cout << gsl_rng_uniform(r.get()) << std::endl;
}
// c++ style usage with unique_ptr
void cpp_unique() {
std::unique_ptr<gsl_rng, void(*)(gsl_rng*)> r(gsl_rng_alloc(gsl_rng_taus), gsl_rng_free);
std::cout << gsl_rng_uniform(r.get()) << std::endl;
}
int main() {
c();
cpp_shared();
cpp_unique();
return 0;
}
the functions gsl_rng_alloc() and gsl_rng_free() are the memory allocaters and deallocaters respectively.
std::shared_ptr<gsl_rng> r(gsl_rng_alloc(gsl_rng_taus), gsl_rng_free);
in the code fragment above gsl_rng is the type of object r points to. notice how the smart pointer constructor is provided with two arguments 1) the custom allocator gsl_rng_alloc() and 2) the custom deleter gsl_rng_free(). however gsl_rng_uniform() expects a const gsl_rng* argument for which we use the get() member function of the shared_ptr class i.e. r.get() returns a pointer to the gsl_rng object it is pointing to.
std::unique_ptr<gsl_rng, void(*)(gsl_rng*)> r(gsl_rng_alloc(gsl_rng_taus), gsl_rng_free);
this one is a bit ugly looking. notice that unique_ptr requires the specification of 2 template parameters, the type of object being pointed to and the type of the custom deleter. the function gsl_rng_free() is declared as void gsl_rng_free(gsl_rng*) thus the type of this deleter is specified as void(*)(gsl_rng*) i.e. a function which accepts a gsl_rng* and whose return type is void. here again one must use the get() member function to get a reference to the pointed to object.
leave comments, rants and improvements!