It depends.
If the loop is in the same scope that declares the array, then it is possible to determine the array's size directly, eg:
{
...
vector<int> a[SomeSize];
for(size_t i = 0; i < SomeSize; ++i){ // OK!
...
}
for(size_t i = 0; i < sizeof(a) / sizeof(*a); ++i){ // OK!
...
}
for(size_t i = 0; i < std::size(a); ++i){ // OK!
...
}
for(auto iter = std::begin(a); iter != std::end(a); ++iter){ // OK!
...
}
for(auto &elem : a){ // OK!
...
}
...
}
On the other hand, if the array is passed to a function, then it is possible to determine the array's size only if the array is passed by reference, or if the size is passed explicitly as a separate parameter, eg:
void func1(vector<int> a[]) // same as 'vector<int>* a'
{
for(size_t i = 0; i < sizeof(a) / sizeof(*a); ++i){ // NOPE, can't work!
...
}
for(size_t i = 0; i < std::size(a); ++i){ // NOPE, can't work!
...
}
for(auto iter = std::begin(a); iter != std::end(a); ++iter){ // NOPE, can't work!
...
}
for(auto &elem : a){ // NOPE, can't work!
...
}
}
void func2(vector<int> *a, int size)
{
for(size_t i = 0; i < size; ++i){ // OK!
...
}
for(auto iter = a; iter != a + size; ++iter){ // OK!
...
}
for(auto iter = std::begin(a); iter != std::end(a); ++iter){ // NOPE, can't work!
...
}
for(auto &elem : a){ // NOPE, can't work!
...
}
*/
}
template<size_t N>
void func3(vector<int> (&a)[N])
{
for(size_t i = 0; i < N; ++i){ // OK!
...
}
for(size_t i = 0; i < sizeof(a) / sizeof(*a); ++i){ // OK!
...
}
for(size_t i = 0; i < std::size(a); ++i){ // OK!
...
}
for(auto iter = std::begin(a); iter != std::end(a); ++iter){ // OK!
...
}
for(auto iter = a; iter != a + N; ++iter){ // OK!
...
}
for(auto &elem : a){ // OK!
...
}
}
vector<int> a[SomeSize];
func1(a);
func2(a, SomeSize);
func2(a, std:size(a));
func3(a);