C ++ Vector Design with Given Memory

I would like to use std :: vector to manage this piece of memory. First of all, I'm sure this is not a good practice, but curiosity is better than me, and I would like to know how to do it anyway.

I have a problem:

vector<float> getRow(unsigned long rowIndex) { float* row = _m->getRow(rowIndex); // row is now a piece of memory (of a known size) that I control vector<float> returnValue(row, row+_m->cols()); // construct a new vec from this data delete [] row; // delete the original memory return returnValue; // return the new vector } 

_m is a DLL interface class that returns a float array that is responsible for removing callers. So I would like to wrap this in a vector and return it to the user ... but this implementation allocates new memory for the vector, copies it, and then deletes the returned memory, and then returns the vector.

What I would like to do is directly tell the new vector that it has full control over this block of memory, so when it is deleted, the memory is cleared.

UPDATE : the original motivation for this (the memory returned from the DLL) was pretty hard crushed by a number of respondents :) However, I would like to know the answer to the question anyway ... Is there a way to build std :: vector using the given fragment allocated an array of T * memory and the size of this memory?

+6
c ++ memory-management vector
source share
6 answers

The default vector allocator does not provide this type of access to its internal elements. You can do this with your own dispenser (the vector parameter of the second template), but this will change the type of vector.

It would be much simpler if you could write directly to the vector:

 vector<float> getRow(unsigned long rowIndex) { vector<float> row (_m->cols()); _m->getRow(rowIndex, &row[0]); // writes _m->cols() values into &row[0] return row; } 

Note that & row [0] is a float *, and it is guaranteed for the vector that it will store elements contiguously.

+4
source share

The obvious answer is to use a custom dispenser, however you may find that it is really quite a difficult decision for what you need. If you want to do this, the easiest way is to make the selection (as an argument to the default template template for the vector <>) an implementation, copy it and make it work as needed.

Another solution may be to determine the specialized specialization of the vector, determine as many of the interface as possible, and implement memory settings.

Finally, what about defining your own container with the appropriate STL interface, defining random access iterators, etc. This can be quite easy, given that the base array will display the vector <> well, and the pointers to it will be displayed in iterators.

UPDATE comment: "Is there a way to build std :: vector using the given fragment of the T * array of allocated memory and the size of this memory?"

Of course, the simple answer here is "No." If you want the result to be a vector <>, then it should support growth as necessary, for example, using the reserve () method, and this is not possible for a given fixed distribution. So, the real question really is: what exactly do you want to achieve? Something that can be used as a vector <> or something that really has a sense in a certain sense, a vector, and if so, what is the point?

+4
source share

The most important thing to know here is that different DLLs / modules have different heaps. This means that any memory allocated from the DLL must be deleted from this DLL (this is not only a matter of the compiler version, either delete vs delete[] or something else). DON'T MISS THE RESPONSIBILITY FOR MANAGING MEMORIES AT THE BORDER. This includes creating std::vector in the dll and returning it. But it also includes passing std::vector to the DLL to populate the DLL; such an operation is unsafe, because you do not know for sure that std::vector will not try to resize any kind while it is filled with values.

There are two options:

  • Define your own allocator for the std::vector class, which uses the distribution function, which is guaranteed to be in the DLL / module from which the vector was created. This can easily be done using dynamic binding (i.e., make the allocator class a call to some virtual function). Since dynamic linking will look in the vtable to call the function, it is guaranteed that it will get into the code from the DLL / module that originally created it.

  • Do not skip the vector object in or out of the DLL. You can use, for example, the function getRowBegin() and getRowEnd() , which returns iterators (i.e. Pointers) in an array of strings (if it is adjacent), and allows the user std::copy in his own local std::vector an object. You can also do it the other way around, pass iterators begin () and end () into a function of type fillRowInto(begin, end) .

This problem is very real, although many people neglect it without knowing it. Do not underestimate this. I personally experienced the silent errors associated with this problem, and it was ugly! It took me months to solve this problem.

I checked in the source code, and boost::shared_ptr and boost::shared_array used dynamic binding (the first option above) to handle this. However, they do not guarantee binary compatibility. However, it might be a little better (usually binary compatibility is a much smaller problem than memory management via modules).

+2
source share

It is best to choose std::vector<shared_ptr<MatrixCelType>> .

More details in this thread .

0
source share

If you are trying to change where / how a vector allocates / reallocates / frees memory, the allocator pattern parameter of a vector class is what you are looking for.

If you are just trying to avoid the overhead of construction, copy the design, purpose and destruction, then allow the user to create an instance of the vector, and then pass it to your function by reference. The user is then responsible for construction and demolition.

It looks like you are looking for the shape of a smart pointer. One that removes what it indicates when it was destroyed. Take a look at the Boost libraries or collapse your own in this case.

0
source share

The Boost.SmartPtr library contains many interesting classes, some of which are designed to handle arrays.

For example, see scoped_array :

 int main(int argc, char* argv[]) { boost::scoped_array<float> array(_m->getRow(atoi(argv[1]))); return 0; } 

The problem, of course, is that scoped_array cannot be copied, so if you really want std::vector<float> , @Fred Nurk is probably the best you can get.

In the ideal case, you need the equivalent of unique_ptr , but in the form of an array, however I do not consider it part of the standard.

0
source share

All Articles