0

I need to init/use a double ** (decleared in my header):

double **pSamples;

allocating (during the time) a matrix of NxM, where N and M are get from two function:

const unsigned int N = myObect.GetN(); 
const unsigned int M = myObect.GetM(); 

For what I learnt from heap and dynamic allocation, I need keyword new, or use STL vector, which will manage automatically allocate/free within the heap.

So I tried with this code:

vector<double> samplesContainer(M);
*pSamples[N] = { samplesContainer.data() };

but it still says I need a constant value? How would you allocate/manage (during the time) this matrix?

markzzz
  • 47,390
  • 120
  • 299
  • 507
  • 2
    `std::vector> samplesContainer(M, std::vector(N));` might be a good alternative to `double**` – Jarod42 Jun 14 '16 at 08:48
  • 1
    Or a flat `std::vector` (`N * M` `double`) wrapped in a class to have the expected indexing. – Jarod42 Jun 14 '16 at 08:49
  • `*pSamples[N] = { samplesContainer.data() };` won't allocate anything it is just assignment, and probably not the one you meant for. since it out of range. – SHR Jun 14 '16 at 08:50
  • @Jarod42: yes, but than I need to pass to a method a double**. So How can I convert later std::vector> samplesContainer(M, std::vector(N)); to a double**? – markzzz Jun 14 '16 at 08:54
  • Programming by guessing does not work. – Lightness Races in Orbit Jun 14 '16 at 09:52

3 Answers3

1

The old fashioned way of initializing a pointer to a pointer, is correctly enough with the new operator, you would first initialize the the first array which is a pointer to doubles (double*), then you would iterate through that allocating the next pointer to doubles (double*).

double** pSamples = new double*[N];
for (int i = 0; i < N; ++i) {
    pSambles[i] = new double[M];
}

The first new allocates an array of double pointers, each pointer is then assigned to the array of pointers allocated by the second new.

That is the old way of doing it, remember to release the memory again at some point using the delete [] operator. However C++ provide a lot better management of sequential memory, such as a vector which you can use as either a vector of vectors, or simply a single vector capable of holding the entire buffer.

If you go the vector of vector way, then you have a declaration like this:

vector<vector<double>> samples;

And you will be able to reference the elements using the .at function as such: samples.at(2).at(0) or using the array operator: samples[2][0].

Alternatively you could create a single vector with enough storage to hold the multidimensional array by simply sizing it to be N * M elements large. However this method is difficult to resize, and honestly you could have done that with new as well: new double[N * M], however this would give you a double* and not a double**.

Tommy Andersen
  • 7,165
  • 1
  • 31
  • 50
  • The single-`vector` is approach is far superior to anything else mentioned on this page, and there's no reason to think that a matrix needs to be trivially resized. I'm astounded to see so much `new` and double-pointers and vectors of vectors in these answers! – Lightness Races in Orbit Jun 14 '16 at 09:53
  • @LightnessRacesinOrbit OP probably have to call a method which accepts `double**`, how can you do it with single vector? – marcinj Jun 14 '16 at 10:18
  • @MarcinJędrzejewski: In that case, you can't. But a library taking `double**` would be extremely poor as that then near-_mandates_ O(N) dynamic allocations and awful memory locality. Hopefully that's not the case here, but the OP did not say. – Lightness Races in Orbit Jun 14 '16 at 10:20
  • @LightnessRacesinOrbit: yes, the library I'm using take `double**` – markzzz Jun 16 '16 at 12:40
1

Use RAII for resource management:

std::vector<std::vector<double>> samplesContainer(M, std::vector<double>(N));

then for compatibility

std::vector<double*> ptrs(M);
for (std::size_t i = 0; i != M; ++i) {
    ptrs[i] = samplesContainer[i].data();
}

And so pass ptrs.data() for double**.

Jarod42
  • 203,559
  • 14
  • 181
  • 302
  • What do you mean with "then for compatibility"? Can't just use `std::vector> samplesContainer(M, std::vector(N));`? Tried this: `vector> samplesContainer(M, vector(N)); pSamples = samplesContainer.data();` but can't assign it to my double** – markzzz Jun 14 '16 at 09:22
  • @paizza: `samplesContainer.data()` is `std::vector*`. your `double **` is done with `ptrs.data()` – Jarod42 Jun 14 '16 at 09:30
  • I see. But why I need to first declare a vector double of double and than another new double for than assign the first vector? Can't I just init one time? – markzzz Jun 14 '16 at 09:34
  • Ok. But I just can't assign vector of double double without iterate it (the for)? – markzzz Jun 14 '16 at 09:56
  • I mean, can't I not use `samplesContainer` and allocate a double of (N) in ptrs[i]? Or can't I use std::vector ptrs(M); and use samplesContainer for the first-level indexes? – markzzz Jun 14 '16 at 10:01
  • any ideas please? I don't get why you init "two times". – markzzz Jun 15 '16 at 12:26
-1

samplesContainer.data() returns double*, bur expression *pSamples[N] is of type double, not double*. I think you wanted pSamples[N].

pSamples[N] = samplesContainer.data();
PcAF
  • 1,975
  • 12
  • 20