0

I ran the following code

#include <vector>
#include <complex>

#define N 8192

int main() {
    std::vector< std::complex<double> > input;
    input.reserve(N);

    for (size_t k = 0; k < N; k++) {
        input[k] = std::complex<double>(k, 0.0);
    }
}

in both codeBlocks and Visual Studios 2019. The latter gives the runtime error "vector subscript out of range", while in codeBlocks it runs fine. What is happening, and how can I fix this?

Pel de Pinda
  • 113
  • 4
  • @mch No, I think reserve is the right choice here because I do it immediately after declaring input. – Pel de Pinda Mar 02 '21 at 21:36
  • @PeldePinda — look at `input.size()` before and after that call to `reserve`. Indexing beyond a vector’s size produces undefined behavior. – Pete Becker Mar 02 '21 at 21:41
  • 1
    You can either change `reserve` to `resize` or `input[k] = std::complex(k, 0.0);` to `input.emplace_back(k, 0);` – mch Mar 02 '21 at 21:42
  • BTW you may use `constexpr` instead of `#define` for compile time constants. – Gary Strivin' Mar 02 '21 at 22:04
  • Fun fact: What you've seen is Undefined Behaviour in action and one of the things that makes it a powerful ally. Microsoft has taken advantage of the fact that the behaviour is not specified to add tests to their debug libraries to help you spot out-of-bounds bugs. These tests do not exist in the release builds because these tests take time and slow your program. If these tests were required, all programs would be slower, even the ones that took steps to never go out of bounds. Microsoft is giving the best of both worlds: bug finding and high performance. But not at the same time – user4581301 Mar 02 '21 at 22:16

2 Answers2

1

http://www.cplusplus.com/reference/vector/vector/reserve/

reserve only guarantees that the vector does not need to reallocate elements until it hits the reserved capacity.

See the example in the provided link for more detail.

Use the resize function to actually resize the container to contain the elements so you won't exceed the capacity.

vector subscript out of range tells you that you attempt to access an index that is not available.

user4581301
  • 33,082
  • 7
  • 33
  • 54
1

First of all, since you know exact size - you can use raw array e.g std::complex<double> input[N]; or std::array instead of vector. In any case the whay you are using STL container like vector or set is wrong. Generally you should use push_back or preferably emplace_back to insert an object to the end of dynamic container. Second note - C++ is not C avoid defining constants like macro. For example:

#include <vector>
#include <complex>
#include <iostream>

int main(int argc, const char** argv) {
    constexpr const std::size_t COMPLEX_COUNT = 8192;
    std::vector< std::complex<double> > input(COMPLEX_COUNT);
    for (std::size_t i = 0; i < COMPLEX_COUNT; i++) {
        input.emplace_back( i, 0.0 );
    }
    for(auto it: input) {
       std::cout << it << ' ';
    }
    std::cout << std::endl;
    return 0;
}

Read some book about STL, like Effective STL by Scott Meyers

Victor Gubin
  • 2,782
  • 10
  • 24