bodacydo
bodacydo

Reputation: 79499

Can I use std::vector<std::vector<T>> to represent two dimensional arrays in C++?

I recently learned how to do two- and three-dimensional arrays in plain C using pointers, however being a C++ enthusiast, I'd also like to figure out how to do multi-dimensional arrays in C++.

I know that the preferred way of doing one-dimensional arrays in C++ is to use std::vector<T>, but what about two- and three-dimensional arrays? Would they be represented as std::vector<std::vector<T>> and std::vector<std::vector<std::vector<T>>>?

Upvotes: 2

Views: 1582

Answers (3)

Vlad from Moscow
Vlad from Moscow

Reputation: 311068

Of course you may use class std::vector to simulate arrays. For example

#include <iostream>
#include <vector>

int main() 
{
    size_t n;
    size_t m;

    std::cout << "Enter the number of rows: ";
    std::cin >> n;

    std::cout << "Enter the number of columns: ";
    std::cin >> m;

    std::vector<std::vector<int>> v( n, std::vector<int>( m ) );

    return 0;
}

Also consider using of the combination of std::vector with std::array when the number of columns is a compile time constant.

A definition of so-called 3-dimensional array can look as for example

std::vector<std::vector<std::vector<int>>> 
    v( 2, std::vector<std::vector<int>>( 3, std::vector<int>( 4 ) ) );

A more interesting example

#include <iostream>
#include <vector>
#include <numeric>

int main() 
{
    size_t n;
    size_t m;

    std::cout << "Enter the number of rows: ";
    std::cin >> n;

    std::cout << "Enter the number of columns: ";
    std::cin >> m;

    std::vector<std::vector<int>> v( n, std::vector<int>( m ) );

    for ( size_t i = 0; i < n; i++ )
    {
        std::iota( v[i].begin(), v[i].end(), i * m );
    }

    for ( const auto &v1 : v )
    {
        for ( auto x : v1 ) std::cout << x << ' ';
        std::cout << std::endl;
    }

    return 0;
}

If to enter 3 and 5 correspondingly for n and m then the output will be

0 1 2 3 4 
5 6 7 8 9 
10 11 12 13 14 

Upvotes: 2

Quentin
Quentin

Reputation: 63154

While you can technically do that, it is a better idea to use a single std::vector<T> and calculate the offsets by hand. The resulting memory layout will be much more cache-friendly, since everything will be tightly packed together and can be traversed sequentially or indexed with no indirection.

However, if C++11 is an option and the size of your array is fixed at compile-time, you should use nested std::arrays. Dynamic allocation can be easily achieved with std::unique_ptr. Note however that the data won't necessarily be strictly contiguous between sub-arrays, which could be a problem when interfacing with API's expecting a single ol' block of data.

Upvotes: 3

Kknd
Kknd

Reputation: 3217

Sure!

#include <vector>
#include <iostream>

int main()
{
    typedef std::vector<double> VD;
    typedef std::vector<VD>    VVD;

    // 10x5 matrix filled with ones
    VVD mtx(10, VD(5, 1));

    std::cout << mtx.size() << " " << mtx[0].size() << std::endl;
    std::cout << mtx[3][2] << std::endl;


    return 0;
}

Upvotes: 1

Related Questions