-1

This is related to this post that talked about .at() vs [] in std::vector. I just want to ask if .at() should be used over the bracket operators? Take the following code example:

#include <vector>
#include <iostream>

void print(const std::vector<int> &v)
{
  for(int i = 0; i < v.size(); ++i)
  {
    std::cout << v.at(i) << " ";
  }
  std::cout << std::endl;
}

int main()
{
  std::vector<int> test = {1,2,3,4};
  print(test);
}

I would not print a vector this way, I would used for(const auto &e : v) and print out every element as that is guaranteed to not go outside the bounds of the vector. However let's say for a minute we are teaching new students about for loops.

Say we change the second argument in our for loop to v.size() + 1. .at(i) will crash and give us a meaningful runtime error std::out_of_range. However if we change .at(i) to be v[i] the program runs fine and prints out an extra number for me. I'm running this on Ubuntu 18.04 on Window's, I thought the program would crash when I did that however it didn't.

So the question stands, should we be using .at() instead of [] when accessing our containers?

Sailanarmo
  • 1,139
  • 15
  • 41
  • 2
    *However let's say for a minute we are teaching new students about for loops.* start them with ranged based for loops and leave the old loops for later when they are more comfortable. – NathanOliver Mar 28 '19 at 18:44
  • This is completely opinion-based. Would you rather have a slightly safer application or a slightly faster application? – HolyBlackCat Mar 28 '19 at 18:45
  • Short answer: yes, because the bounds checking will throw a relevant exception on an out-of-bounds access rather than a segfault. – Tzalumen Mar 28 '19 at 18:46
  • @HolyBlackCat Note: safer, not more stable. (`.at` failure often leads to catestrophic application failure unless your code is very exception safe; meanwhile, `[]` failure leads to memory corruption and very very rarely segfaults) – Yakk - Adam Nevraumont Mar 28 '19 at 18:46
  • @HolyBlackCat, wouldn't we want all applications to be safer? – Sailanarmo Mar 28 '19 at 18:46
  • 1
    What exactly is not clear to you in the link you have provided yourself? I do not see how I can add anything to the answer **already** there. – SergeyA Mar 28 '19 at 18:46
  • @SergeyA, I am asking if .`at()` should completely replace `[]` entirely in newer code bases. I understand everything in the link I provided. – Sailanarmo Mar 28 '19 at 18:47
  • 1
    @Sailanarmo safety is always traded for usability, in every aspect of our life, including software development. When investing money, do you want lower risk or higher returns? – SergeyA Mar 28 '19 at 18:47
  • 1
    Related question https://stackoverflow.com/q/6911289/3235496 – manlio Mar 28 '19 at 18:48
  • The one of the major requirements and design goal for vector/std::array was to have as little as possible overhead over plain old c structures if used in that context. Back in the days, the speed was one of the major selling points. Now , I would say that for 99% of the written code safety should come first. But again, this is an opinion – Dr Phil Mar 28 '19 at 18:48
  • 3
    @DrPhil My opinion would be that if performance doesn't matter to you, you probably should be using different language. – SergeyA Mar 28 '19 at 18:49
  • @Sailanarmo Remember that most standard libraries have fancy options for checking container bounds and maybe iterator validity (`-D_GLIBCXX_DEBUG` for libstdc++ and so on). If you want safety, I suggest using these instead of `.at()`. – HolyBlackCat Mar 28 '19 at 18:49
  • 1
    For those voting to close, would you mark it as a dup instead? I think @manlio's post is the question I was really asking. – Sailanarmo Mar 28 '19 at 18:51
  • btw if you ever teach students about for loops and need an example of an index based for loops then please use an example where using the index actually makes sense, not one where you actually would use a ranged based for loop ;) – 463035818_is_not_an_ai Mar 28 '19 at 18:51
  • @user463035818 haha, I know. I was just trying to think of a very simply example. – Sailanarmo Mar 28 '19 at 18:52
  • Re: ".at(i) will crash" -- no. It will throw an exception. If your program doesn't catch that exception, your **program** will crash. – Pete Becker Mar 28 '19 at 19:24

1 Answers1

4

Should .at() be used over [] in std::vector or std::array?

Yes, if

  • You are unable to prove that the index you access is within bounds.
  • You don't want to bother proving that.
  • You might make a mistake in your proof or in your implementation (for humans, this is "yes" most of the time), and undefined behaviour in your program is more costly than the overhead of at.

No, if

  • You cannot afford the overhead of at.

It doesn't matter much, if

  • Your program isn't used in situations where undefined behaviour could result in loss (or leaking) of information, anything of monetary value, life etc.

let's say for a minute we are teaching new students

Using at is particularly useful to new students whose ability to reason about the correctness of their program has not yet developed.

On the other hand, understanding undefined behaviour is also essential to C++ programmers, and vector subscript and its caveats need to also be introduced to students... at some later time when they are already comfortable with vectors.

eerorika
  • 232,697
  • 12
  • 197
  • 326
  • 1
    Most standard library have a debug level to do extra debug checking – JVApen Mar 28 '19 at 18:52
  • 1
    Why not use `assert` and fix the bug if there is one? – manlio Mar 28 '19 at 18:57
  • 1
    @manlio because 1. `assert` cannot be handled gracefully like an exception can be handled and because 2. assertions are usually disabled in release mode and most people don't have the time or ability to test 100% of possible use cases. – eerorika Mar 28 '19 at 19:00