0

I'm new to c++ and just learned about vectors. I'm coming from Python, so of course I checked if I could use negative indexing in c++, which did not seem to work.

While trying to check if it works, I met a very weird behaviour for negative indexes in different environments.

Using negative indexes with the .at() function raises an error but not when using [] brackets.

Are these values contents of previous memory locations, or what do they represent? Is this what's called undefined behaviour?

Source:

#include <iostream>
#include <vector>

int main() {
  std::vector<int> numbers = {3, 6, 9, 12, 15};
  std::cout << "Length: " << numbers.size() << "\n";
  for (int i = 4; i > -5; i--) {
    std::cout << "Pos " << i << ": " << numbers[i] << "\n";
  }
}

Output:

Length: 5
Pos 4: 15
Pos 3: 12
Pos 2: 9
Pos 1: 6
Pos 0: 3
Pos -1: 0   // other env: 201392090
Pos -2: 33  // other env: 475047512
Pos -3: 0
Pos -4: 0
Rafael
  • 525
  • 7
  • 20
  • 4
    Yes, this is what is called _undefined behavior_. – Daniel Langr Dec 20 '21 at 11:00
  • 4
    if you are coming from Python you better get used to the idea that you need to learn a new language from scratch. Pythonic C++ code won't work out well – 463035818_is_not_an_ai Dec 20 '21 at 11:00
  • 1
    https://en.cppreference.com/w/cpp/language/ub -> Access out of bounds – 463035818_is_not_an_ai Dec 20 '21 at 11:03
  • 1
    When you put some number `pos` in bracket as index for `vector`, it essentially means `vector.begin() + pos`. Here, `vector.begin()` is the pointer to the first element of the vector. If your `pos` is negative then it's just going to show you data from some other memory location. – Abdur Rakib Dec 20 '21 at 11:05
  • 1
    Also a suggestion, python indexing and c++ indexing are fairly different. Learn c++ from scratch without referring to your python knowledge. And for vector, it's better to use iterator instead of bracket index. – Abdur Rakib Dec 20 '21 at 11:07

2 Answers2

2

Are these values contents of previous memory locations, or what do they represent? Is this what's called undefined behaviour?

No, it's not actually accessing a memory location prior to the beginning of the backing array, but one past the end:

If you use numbers [index], the compiler interprets this as numbers.operator[](index), i.e. the member function operator[]() is used. This function takes a parameter of type size_t which is an unsigned integer. The parameter -1 is implicitly converted to a unsigned integer yields a very large number and this number is out of range of values the contract of std::vector covers. Read or write access to such an element is undefined behaviour. at in contrast to operator[]() does compare the parameter to the vector size guaranteeing an exception in this scenario, but with operator[] there's no such "safety net".

fabian
  • 80,457
  • 12
  • 86
  • 114
2

You can use negative indexing in C++, not just on a container that starts at index 0.

However, you can have an iterator into the middle of a vector and index from that.

std::vector<int> numbers = {3, 6, 9, 12, 15};
std::vector<int>::iterator it = numbers.begin() + 3;
std::cout << it[-2];
BoP
  • 2,310
  • 1
  • 15
  • 24