[Top][All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Help-gsl] Just getting started - I have some 'newbie' questions.

From: Maxime Boissonneault
Subject: Re: [Help-gsl] Just getting started - I have some 'newbie' questions.
Date: Thu, 22 Mar 2012 09:04:42 -0400
User-agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.7; rv:10.0.2) Gecko/20120216 Thunderbird/10.0.2

I suspected as much.

I have seen various people recommending different ways of getting a pointer to 
the first element of an std::vector, but they all miss a couple things.  The 
last I checked, the way memory is allocated and managed in an STL container is 
an implementation detail, so there is no guarantee that the contents of a 
vector are stored in contiguous memory.  Unless the standard has changed since 
last I looked to provide such a guarantee, I wouldn't want to make such an 
assumption.  Further, all bets are off when it comes to member functions that 
can change the contents of the vector.  One of the frequent issues I see junior 
programmers having is that they forget that all iterators are invalidated when 
you start adding or removing elements.

Alas, this guarantees some inefficinecies, especially when there is a need to 
use multiple libraries.  For example, I have written a library that is quite 
efficient in use of std::vector in computing various statistics, especially 
moving statistics.  But it depends on the capabilities of std::vector, and 
especially its forward and reverse iterators, for much of its efficiencies.  To 
use both that code and gsl in the same program, I guess there's little option 
but to use gsl's vector view and matrix view on pointers to double arrays (and 
at least with those I can guarantee exception safety by having the memory those 
arrays use managed by a smart pointer), and bear the cost of one copy of the 
input data each time the analysis is required.  At least, when doing this for a 
time series, and needing a moving window, I can avoid the cost of reallocating 
the memory used for the data.
That is not quite correct. The C++ Standard guarantees that vectors are stored such that the i-th element of a vector v is stored in memory at the address (&v[0]+i) for all i's. This is the case since C++03. You are however correct that this was not the case before C++03.

A similar addition to the standard have also been done for the complex<T> type. Before C++11, the real and imaginary parts of complex<T> were not garanteed to be contiguous in memory, and I think there was no guarantee that there were no padding of some sort. C++11 guarantees that. That is, if you have :
complex<double> carray[10];
You are certain that :
((double *)carray)[2*i]      => gives the real part of the i-th element
((double *)carray)[2*i+1] => gives the imaginary part of the i-th element.

In practice, it is probable that all implementations of vector and complex were done this way from the start, but when the C++ standard comitee realized that these two things were not guaranteed by the standard, they fixed it (because it would break a lot of codes using legacy C or Fortran libraries if this was not the case).

Since C++03, you can therefore safely use a "vector<double> v" and pass "&v[0]" to a C function requiring a "double *", and since C++11, you can safely cast "complex<T> *" into a "double *" (which will have twice the length of the initial vector) to a C (or Fortran) function which expects arrays of T to represent arrays of complex T numbers.


Maxime Boissonneault

reply via email to

[Prev in Thread] Current Thread [Next in Thread]