C++: Constructing a std::vector<std::vector<int> > with a two-dimensional C-array?

10,957

Solution 1

int map[18][25] = { /*...DATA GOES HERE...*/ };
std::vector<std::vector<int> > m;
m.reserve(18);
for (std::size_t i = 0; i != 18; ++i)
    m.push_back(std::vector<int>(map[i], map[i] + 25));

In C++11, you can optionally replace the last line with the following to remove a little noise:

    m.emplace_back(map[i], map[i] + 25);

Solution 2

Why do you want to do that? You have a contiguous block of memory and you are turning that into multiple blocks of memory. I would suggest that rather than that you provide a matrix class that encapsulates the contents of a single std::vector<int> of size 18*25 and provides accessors (operator()( int, int )) for the elements that accesses col + row*columns...

More in the C++ FAQ lite entry for operator overloading.

Share:
10,957
Casey
Author by

Casey

C++ programmer with over 15 years experience.

Updated on June 14, 2022

Comments

  • Casey
    Casey almost 2 years

    A std::vector can be constructed using a C-array like so: std::vector<int> vec(ary, ary + len). What is the proper way to construct a std::vector<std::vector<int> >?

    I've been brute-forcing the issue by manually copying each element into the vector, clearly this is not the intent, but it works.

    int map[25][18] = { /*...DATA GOES HERE...*/ }
    std::vector<std::vector<int> > m(18, std::vector<int>(25, 0));
    for(int y = 0; y < 18; ++y) {
        for(int x = 0; x < 25; ++x) {
            m[y][x] = map[y][x];
        }
    }
    
  • HighCommander4
    HighCommander4 about 12 years
    In addition to removing a little noise, emplace_back() is a little more efficient as well (since no moving has to be performed).
  • ildjarn
    ildjarn about 12 years
    +1 Agreed entirely, and here's a link to a proper existing, pre-tested matrix library: Boost.uBLAS.
  • Casey
    Casey about 12 years
    -1. In addition to not answering the question you tried to tell me to create a class that's not even remotely related.
  • David Rodríguez - dribeas
    David Rodríguez - dribeas about 12 years
    @Casey: I am not sure you understood the suggestion. The answer I provided is that in most cases you don't want to do what you are asking for, but rather create a type (or use one like ildjarn points out) that encapsulates the matrix, and for which you can then decide how to implement. There is a clear advantage of using a sequential block of memory, and the fact that you have a type that encapsulates the operations allows you to do so. This class is closer binary-wise to the original array than a std::vector<std::vector<int>> because of the different layout.
  • David Rodríguez - dribeas
    David Rodríguez - dribeas about 12 years
    @Casey: ... This includes the use with legacy components that might be expecting the former array, where you can obtain a bitwise compatible structure by casting the contents of the single vector into an array of the proper shape (I don't like casting, and I would rather refactor older interfaces, but the fact is that you can do it). Don't take me wrong, I don't care about the rep, if you don't like it downvote, but there is probably more value in the answer than what you seem to see in the first place.