0

Numerous questions/answers inform me that std::vector<T>::resize(n) will increase capacity and size, whilst std::vector<T>::reserve(n) only increases capacity.

One example is Choice between vector::resize() and vector::reserve().

A comment in that question indicates that after use of reserve(n), the use of

vec[i less than n] = ..

is undefined behaviour, and many examples given are claimed to lead to segfaults.

When I compile and run

#include <vector>
#include <iostream>

void f(const std::vector<double> &s) {
    std::cout << "s.size() = " << s.size() << std::endl;
    std::cout << "s.capacity() = " << s.capacity() << std::endl;
}

int main() {
    std::size_t n = 20121;
    
    std::vector<double> a;
    a.reserve(2*n);
    a[n] = 2.5;
    std::cout << "a["<<n<<"] = " << a[n] << std::endl;
    f(a);
    
    std::vector<double> b;
    b.resize(2*n);
    b[n] = 2.5;
    std::cout << "b["<<n<<"] = " << b[n] << std::endl;
    f(b);
}

my output is

a[20121] = 2.5

s.size() = 0

s.capacity() = 40242

b[20121] = 2.5

s.size() = 40242

s.capacity() = 40242

Questions:

Has there been a change that makes this ok? Is this just my compiler (g++ v5.2.0) giving me undefined, but nice, behaviour?

As a second point of curiosity, why does f(a) tell me the size is 0 (guessed answer: no push_back calls), even though a[n] returns a valid value?

Community
  • 1
  • 1
chrisb2244
  • 2,940
  • 22
  • 44
  • 2
    Your program exhibits undefined behavior. "Appears to work" is one possible manifestation of undefined behavior. `f(a)` tells you that the size is 0 because the size is in fact 0; as you yourself mentioned at the start, `reserve()` modifies capacity but not size. – Igor Tandetnik Oct 13 '15 at 04:45
  • 1
    Try [`-D_GLIBCXX_DEBUG`](http://stackoverflow.com/questions/5594686/gcc-stl-bound-checking) – dyp Oct 13 '15 at 04:46
  • It is UB. Use class type (`std::string` or so) instead of vector `double`. Maybe a more complex type would cause your program result in crash. – Nawaz Oct 13 '15 at 04:46
  • 1
    Define "nice" undefined behavior! I would want the compiler to crash the program if I trigger undefined behavior. I consider it hostile to rather do something some people might expect! Run your code with some of the sanitizers and there should be a report of the issue: that's "nice". – Dietmar Kühl Oct 13 '15 at 04:47
  • @dyp `-D_GLIBCXX_DEBUG` refuses to compile with `out-of-bounds`, which is perhaps more 'nice' in this case. – chrisb2244 Oct 13 '15 at 04:54
  • @Nawaz Using `std::string` gives me the same result as with `double`, but I see the point you're making. – chrisb2244 Oct 13 '15 at 05:05
  • You really need to read [What is undefined behaviour?](http://stackoverflow.com/a/4105123/1505939) – M.M Oct 13 '15 at 05:26

2 Answers2

1

By definition "Undefined Behavior" means that the result that you see on the execution of that line is not defined and can/will change with different runs.

Is this just my compiler (g++ v5.2.0) giving me undefined, but nice, behaviour?

The nice behavior can be a mix of how std::vector is implemented in the version you are compiling and the state of memory when your program was executed. The compiler has almost no role to play in showing a "nice behavior".

One line answer: What you are noticing is indeed undefined behavior. The runtime is free to give any output/behavior including shooting monkeys out of your monitor, on hitting an UB.

bashrc
  • 4,725
  • 1
  • 22
  • 49
0

As always with undefined behavior, your compiler may produce what you might think would be a "reasonable/nice" behavior, but the fact that you're seeing "nice" behavior doesn't mean that what you're doing is okay! This behavior may change at any time, with any new version of the compiler, when you compile and/or run it on any other machine or OS, or when you re-run your program during a different lunar phase.

Aasmund Eldhuset
  • 37,289
  • 4
  • 68
  • 81