vectors: how create and initializate multidimensional?

Pages: 123
Using range based for loops on a vector that you have resized makes sure you don't either go out of bounds or not access all elements.

What if you have resized your vector to 10 instead of 20. Your for loop at lines 20-23 would have gone out of bounds.

If you had resized to 30 instead of 20, 10 vectors would have been unfilled.
thank you so much for all...
the 'for (auto& itr : vec)' loop style is new for me ;)
I know I had this question, maybe you do as well.

"Can a vector's element(s) in a range-based for loop be deleted?"

No. :)

https://stackoverflow.com/questions/10360461/removing-item-from-vector-while-in-c11-range-for-loop
the 'for (auto& itr : vec)' loop style is new for me ;)

That is a "range-based" for loop. Also known as a for-each loop.

A range-based for loop is guaranteed to access every element in a container, and impossible to go out-of-bounds.

There are several variations of the loop.

https://en.cppreference.com/w/cpp/language/range-for
thank you so much for all
Thank YOU. Your questions made me delve deeper into the bowels of how vectors work. I would never have thought about using std::vector::resize and std::fill to add elements to an empty vector.

Now I know. :)

Personally I prefer to create a vector with a known size. std::iota works for that.
try these code lol
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
#include <iostream>
#include <vector>

using namespace std;

int main()
{
    //creating a 2D vector:
    vector<vector<int>> vec;
    
    //creating a 3D vector:
    //vector < vector < vector < int > > > vec;
    //the number of dimensions is the number of 'vector' and '<'\'>'
    
    
    //resize the 1st dimension:
    vec.resize(20);//we must resize the 1st dimension for we start
    
    //now resize the 2nd dimension from the 1st(yes... 1st dimension all elements)
    for (auto& itr1 : vec)
    {
       itr1.resize(20); 
    }
    //if we have more dimensions, we make the same...
    
    
    //change all 'vec' elements to '10':
    for (auto& itr : vec)
    {
        std::fill(itr.begin(), itr.end(), 10);
    }   
    
    //get 1 element out put:
    cout << vec[19][45];//heres the 45 change
    
    return 0;
}

the output is zero lol but out of range lol
The output could be zero, or another garbage value. It could even crash the program.

Using operator[] does no bounds checking. Going out of bounds causes undefined behavior.

std::vector::at member function does check for out of bounds.

Change line 34 to std::cout << vec.at(19).at(45) << '\n';

Compile, run and *BOOM!* That code crashes and burns, big time, by throwing an uncaught exception.
Last edited on
hehehe true.
thanks for all
(just for playing and learn more)
i'm sorry, but can i convert these line:
std::vector<std::vector<int>> vec2(rows, std::vector<int>(cols));
to a macro?
i did these:
#define multivector(tipo, nome,...) std::vector<std::vector<tipo>> nome(__VA_ARGS__, std::vector<tipo>(cols));
but i can't or don't know control:
- the 'vector' word times;
- and their sizes...
use typedef if you want to condense a frequently used vector def to a name.
macros work but are troublesome and its best to not get in the habit of using them when not necessary.

you can build up several smaller types into a big one, adding a dimension each time, if you want.
Use typedef or using:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
#include <iostream>
#include <vector>
#include <numeric>
#include <algorithm>

int main()
{
   using _1Dvec = std::vector<int>;

   _1Dvec vec(10);

   std::iota(vec.begin(), vec.end(), 100);

   std::cout << vec.at(5) << '\n';

   using _2Dvec = std::vector<_1Dvec>;

   _2Dvec vec2(10);

   for (auto& itr : vec2)
   {
      itr.resize(10);
      std::fill(itr.begin(), itr.end(), 100);
   }

   std::cout << vec2.at(3).at(7) << '\n';
}
Use typedef or using:


This is where the thread started. We have come full circle.
Apparently the OP missed your earlier comment, doug4. I responded to his "can I use a macro" question from yesterday.
IMHO, Ganado did show a good path.

Remember, std::vector is 1D. Nothing more, nothing less. 1D.

If you want multi-dimensional container, then define such:
1
2
3
4
5
6
7
template <typename T>
class MyNDimArray {
  // interface for N-dimensional "vector"
private:
  std::vector<T> data; // #X
  // other necessary members
};

#X: vector is ok internal storage for "full matrix".
The "vector of vectors" shown in multiple posts can be a "ragged matrix".
A "sparse matrix" is yet different case.
i'm sorry.. different time: 09:03PM
thank you so much for all
i was trying avoiding repeat the 'vector<int>' several times on type and on initialization size\value
now i did something cool, but with macros:
(yes i know what you said)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#include <iostream>
#include <vector>

#define vector2D(type, name, size1,size2, defaultvalues) \
std::vector<std::vector<type>> name(size1,std::vector<type>(size2, defaultvalues))
#define vector3D(type, name,size1, size2,size3, defaultvalues) \
std::vector<std::vector<std::vector<type>>> name(size1, vector<vector<type>>(size2, vector<type>(size3,defaultvalues)))
#define vector4D(type, name,size1, size2,size3, size4, defaultvalues) \
std::vector<std::vector<vector<vector<type>>>> name(size1, vector<vector<vector<type>>>(size2, vector<vector<type>>(size3,vector<type>(size4,defaultvalues))))

using namespace std;

int main()
{
    vector4D(int, vec2, 20,20,30,23,45);
    
    cout<<vec2[0][0][0][0];

    return 0;
}

it's the best code that i did... the 'typedef' don't works with these situation... the template must return using 'auto'... so i did these code ;)
let me ask: is there any situation with more than 4D? normaly we use 2D
Last edited on
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
#include <vector>
#include <iostream>

template <typename T>
struct CompleteVector{
    T value;
    CompleteVector(const T &value = {}) : value(value){}
    CompleteVector(T &&value) : value(std::move(value)){}
    CompleteVector(const CompleteVector &) = default;
};

template <typename T>
CompleteVector<T> complete(const T &x){
    return CompleteVector<T>(x);
}

template <typename T>
struct VM{
    std::vector<size_t> dimensions;
    VM() = default;
    template <typename T2>
    VM(const VM<T2> &x) : dimensions(x.dimensions){}
    template <typename T2>
    VM(VM<T2> &&x){
        this->dimensions = std::move(x.dimensions);
    }
    VM<std::vector<T>> operator<<(size_t n) const{
        VM<std::vector<T>> copy = *this;
        copy.dimensions.push_back(n);
        return copy;
    }
    template <typename T2>
    T operator<<(const CompleteVector<T2> &n) const{
        T ret;
        initialize(ret, n.value, &this->dimensions[0], this->dimensions.size());
        return ret;
    }
private:
    template <typename V, typename T2>
    static void initialize(V &dst, const T2 &value, const size_t *sizes, size_t n){
        dst.resize(sizes[0]);
        for (auto &i : dst)
            initialize(i, value, sizes + 1, n - 1);
    }
    template <typename T2>
    static void initialize(std::vector<T2> &dst, const T2 &value, const size_t *sizes, size_t n){
        dst.resize(sizes[0], value);
    }
};

int main(){
    auto vec2 = VM<int>() << 2 << 3 << 4 << 5 << complete(42);
    std::cout << vec2.size() << std::endl;
    std::cout << vec2[1][2][3][4] << std::endl;
    auto vec3 = VM<int>() << 2 << 3 << 4 << 5 << 6 << 70 << 8 << complete(42);
}
Last edited on
thanks.. better is using the '[]' or '[size]' instead the '<<'.. but seems great...
i'm sorry, but you do:
auto vec2 = VM<int>()....
isn't more easy like(like) 'vector<type> varname'?
ok.... i use a macro(it's different, because i use a function), but seems more simple to use, i think
i'm sorry, but you do:
auto vec2 = VM<int>()....
isn't more easy like(like) 'vector<type> varname'?
Well, that doesn't declare an std::vector<int>, does it? It declares an std::vector<std::vector<std::vector<std::vector<int>>>>.

ok.... i use a macro(it's different, because i use a function), but seems more simple to use, i think
To each his own. You have to define a separate macro for each dimensionality, while this method lets you have as many dimensions as you want (or as many as the compiler will parse before running out of template depth.
Pages: 123