views:

638

answers:

4

I am writing a Matlab extension using the C++ ublas library, and I would like to be able to initialize my ublas vectors from the C arrays passed by the Matlab interpeter. How can I initialize the ublas vector from a C array without (for the sake of efficiency) explicitly copying the data. I am looking for something along the following lines of code:

using namespace boost::numeric::ublas;

int pv[10] = { 5, 5, 5, 5, 5, 5, 5, 5, 5, 5 };
vector<int> v (pv);

In general, is it possible to initialize a C++ std::vector from an array? Something like this:

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

int main()
{
    int pv[4] = { 4, 4, 4, 4};
    vector<int> v (pv, pv+4);

    pv[0] = 0;
    cout << "v[0]=" << v[0] << " " << "pv[0]=" << pv[0] << endl;

    return 0;
}

but where the initialization would not copy the data. In this case the output is

v[0]=4 pv[0]=0

but I want the output to be the same, where updating the C array changes the data pointed to by the C++ vector

v[0]=0 pv[0]=0
A: 

I don't think C++ allows that convention like C does.

Chris
Of course it does.Pointers are just a specific case of iterators (given a pointer you can deference with * and you can get the next item with ++. That's all you need to initialize a std::vector).
Tristram Gräbener
+3  A: 

You can initialize a std::vector from a C array easily:

vector<int> v(pv, pv+10);
ebo
Thanks for your answer, but this would copy the data. I want `v` and `pv` to point to the same block of data.
celil
You can't have that. std::vector always owns its memory. You can write your own vector class though...
shoosh
+5  A: 

Both std::vector and ublas::vector are containers. The whole point of containers is to manage the storage and lifetimes of their contained objects. This is why when you initialize them they must copy values into storage that they own.

C arrays are areas of memory fixed in size and location so by their nature you can only get their values into a container by copying.

You can use C arrays as the input to many algorithm functions so perhaps you can do that to avoid the initial copy?

Charles Bailey
Except that *in theory* you could create a subclass of ublas::vector that did this. Your subclass could behave as a const ublas::vector that could never be resized, or you'd have to override all of the methods involved in resizing the container to insure that the don't free up memory that doesn't belong to it. Only a complete masochist would attempt this.
Die in Sente
+5  A: 

I'm not sure how your question relates to MATLAB/MEX, but a side note, you might want to know that MATLAB implements a copy-on-write strategy.

This means that when you copy an array for example, only some headers are actually copied, while the data itself is shared between the two arrays. And once one of them is modified, a copy of the data is actually made.

The following is a simluation of what might be happening under the hood (borrowed from this post):

-----------------------------------------
>> a = [35.7 100.2 1.2e7];

 mxArray a
    pdata -----> 35.7 100.2 1.2e7
  crosslink=0

-----------------------------------------
>> b = a;

 mxArray a
    pdata -----> 35.7 100.2 1.2e7
  crosslink     / \
    |  / \       |
    |   |        |
    |   |        |
   \ /  |        |
   crosslink     |
 mxArray b       |
    pdata --------

-----------------------------------------
>> a(1) = 1;

mxArray a
    pdata -----> (1) 100.2 1.2e7
  crosslink=0


   crosslink=0
 mxArray b
    pdata ------> 35.7 100.2 1.2e7 ...

I know this doesn't really answer your question, I just thought you might find the concept helpful.

Amro
You can see this meta-data in the MATLAB Command Window setting format with `format debug`
Mikhail
cool trick, thanks for sharing
Amro