2

If you already know the number of elements you want to do comparisons on (in my case, 5), is it better to use std::array or std::vector?

for(int i=1; i<a.size(); i++)
   if(a[0] != a[i]){
      std::cout << "One or more elements are not equal" << std::endl;
      break;
   }
}

and

for(int i=1; i<myvector.size(); i++)
   if(myvector[0] != myvector[i]){
      std::cout << "One or more elements are not equal" << std::endl;
      break;
   }
}

The only difference is one uses std::array and the other uses std::vector, but is there a reason to use one over the other in this case given you know the specific number of elements?

Javia1492
  • 862
  • 11
  • 28
  • 3
    Both of these approaches will work with `std::vector` and `std::array`. Your examples don't seem to support your question. – François Andrieux Jun 28 '17 at 14:15
  • @FrançoisAndrieux Yes, sorry. I edited the `std::vector` example to make it a `for` loop. – Javia1492 Jun 28 '17 at 14:21
  • So what is the difference between those two code samples now? It's unclear what you are asking – UnholySheep Jun 28 '17 at 14:23
  • @UnholySheep My question is is it better to use an `std::array` or `std::vector` for comparison if i already know the number of elements beforehand. There is no difference other than one is an `std::array` and one is a `std::vector`. – Javia1492 Jun 28 '17 at 14:24
  • 3
    What does better mean? – EvilTeach Jun 28 '17 at 14:25

2 Answers2

4

If you know the size at compile time, use std::array. It has two advantages:

  1. No dynamic allocation (and accordingly, also no pointer dereference accessing the internal array).
  2. The value of size() is known at compile time, making it easier for the compiler to optimize. For instance, a short loop with only 5 iterations will probably be unrolled, eliminating conditional branches.

Btw, your edit that made the two checks similar makes your question more focused and that's good, but idiomatic C++ suggests minimal use of explicit loops. So the std::adjacent_find was even better, and could be used on both containers.

Eran
  • 21,632
  • 6
  • 56
  • 89
  • I never used `std::adjacent_find` before but saw it in a question about element comparison for `std::vector` and assumed it was a function only available to `std::vector`, but Ill read up on it and switch from loops to `std::adjacent_find`. – Javia1492 Jun 28 '17 at 14:32
  • @Javia1492 Standard algorithms generally operate on iterators and do not care about the actual container type. Each algorithm has requirements on the iterators it accepts and as long as your container's iterators meets these requirements, the algorithm will work with your container. This is also true for user implemented containers, provided your container's iterators are properly implemented. See [Iterator concept](http://en.cppreference.com/w/cpp/concept/Iterator). – François Andrieux Jun 28 '17 at 14:37
  • 1
    _No dynamic allocation_ ... this can also be a **disadvantage** of `std::array`: it can cause a stack overflow if your data doesn't fit into stack space. Stack usually is limited to a fixed size configured at compile time (for instance, default size used by MSVC is just 1 MiB). – zett42 Jun 28 '17 at 14:38
  • @Javia1492 `std::vector is a sequence container that encapsulates dynamic size arrays` You don't need a "dynamic size array" here. – cppxor2arr Jun 28 '17 at 14:46
  • *but idiomatic C++ suggests minimal use of explicit loops* not really the case IMO, it all depends on the user's comfort. Range based for loops work better than most `for_each` methods and the like. For simple things explicit loops can often be good enough and idiomatic. Even more the case for things like `istream` input and the like – Curious Jun 28 '17 at 14:56
  • @Curious I'm not a purist, and I don't think using a tight for loop like this is a big issue. I mentioned it since the initial question contained both patterns, and simple cases like this are a good place to get used to avoiding explicit loops. – Eran Jun 28 '17 at 15:21
4

Since eran listed the advantages of std::array I will list the advantages of std::vector.

  1. It is faster to move. The move constructor/assignment operator of a std::vector is little more than the copy of a few pointers (an O(1) operation). Moving a std::array requires moving each individual element (an O(n) operation).
  2. It is less likely to cause a stack overflow. No matter how many elements a std::vector has, it will only keep a small footprint on the stack. The elements of a std::array are part of the object itself, so if it is on the stack, then all of its elements are on the stack. This is probably not a problem if you only have 5 elements, like you said.
  3. It provides more control over when objects are constructed and destroyed. std::array has to create all its instances on initialization. This can be particularly inconvenient when your type doesn't have a default constructor, as you will be required to type out all of the initializations individually. With a std::vector, you can do the constructions in a loop, or at your leisure.
Benjamin Lindley
  • 101,917
  • 9
  • 204
  • 274
  • 1
    Also provides more control over when objects are constructed and destroyed. `std::array` has to create all its instances on initialization – Curious Jun 28 '17 at 14:55
  • 1
    @Curious: Good call. Added. – Benjamin Lindley Jun 28 '17 at 15:01
  • While at it, you can also mention that if the array is beyond a certain size (probably way smaller than the size that will overflow the stack), the compiler will generate a loop anyway, since unrolling will generate too much code. – Eran Jun 28 '17 at 15:24