0
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;

vector<vector<float>> func(int M)
{
    // res = matrix size MxM
    vector<vector<float>> res;
    float* buffer = static_cast<float*>(malloc(M * M * sizeof(float)));
    res.reserve(M);
    for (int i=0; i<M; i++) {
        res.emplace_back(buffer + i * M, buffer + (i + 1) * M);
        /// res[i] = compute_the_matrix();
    }
    
    return res;
}

I'm required to make a function that use vector<vector<float>> to represent a matrix. However, it's inefficient because the rows might be at different location in memory, while a good matrix should have all its element in a continuous block.

To do this, I malloc a continuous block of memory. Then initialize the vectors from this block.

Is this method safe and will the vectors free memory correctly when it's destructed? Another situation I can think of is if there's an exception in res[i] = compute_the_matrix();, then we have a memory leak.

Edit: I think this code perform copy-constructor instead of move-constructor, so it's not what I'm looking for. So, how can I make a vector that is continuous in memory?

Huy Le
  • 1,439
  • 4
  • 19
  • 1
    I don't know what you think you're doing here, but this function will allocate `M` vectors of length `M` which have no guarantee about memory contiguity relative to one-another, and you initialize them with uninitialized data that you allocated with `malloc`, then you leak that memory before returning the vectors. A better approach is to avoid using vector-of-vector altogether. Use a single vector and wrap it in a simple class that you can then use to access the data. You can even use array-like operator overloads to make it feel more familiar. – paddy Jun 15 '22 at 03:48
  • Yes I've noticed and pointed that out in the edit. I wish the buffers of these `M` vectors to be continuous in memory. Is there any way to achieve this? I'm aware that avoiding vector-of-vector is the best solution, but using `vector` is a requirement constraint – Huy Le Jun 15 '22 at 03:49
  • 1
    The only way to make the buffers of a vector-of-vector contiguous is to use a custom allocator, but then you'll wind up in a whole new and horrible scenario that can be avoided if you just use a better data type to begin with. – paddy Jun 15 '22 at 03:50
  • 1
    @HuyLe It is impossible then. – user17732522 Jun 15 '22 at 03:52
  • 1
    Check out an [answer I wrote](https://stackoverflow.com/a/15799557/1553090) a while ago, also in response to someone's vector-of-vector question. This shows you how to make a contiguous data structure for a MxN matrix. – paddy Jun 15 '22 at 03:54

1 Answers1

1

The code doesn't do what you think it does.

The line

res.emplace_back(buffer + i * M, buffer + (i + 1) * M);

creates a new std::vector<float> to add to res. This std::vector<float> will allocate its own memory to hold a copy of the data in the range [buffer + i * M, buffer + (i + 1) * M), which also causes undefined behavior because you never initialized the data in this range.

So, in the end you are not using the memory you obtained with malloc at all for the vectors. That memory is simply leaked at the end of the function.


You can't specify what memory a vector<vector<float>> should use at all. There is simply no way to modify its allocation strategy. What you can do is etiher use a vector<float> instead to hold the matrix entries linearly indexed in a single vector or you can use a vector<vector<float, Alloc1>, Alloc2> where Alloc1 and Alloc2 are some custom allocator types for which you somehow specify the allocation behavior so that the storage layout is closer to what you want (although I doubt that the latter can be done nicely here or is worth the effort over just using the linear representation).

user17732522
  • 53,019
  • 2
  • 56
  • 105
  • Hmm then I guess this requirement is impossible. I know the correct solution, just wondering if this one also works. Thanks – Huy Le Jun 15 '22 at 03:54