5

Our team just ran into the same issue described here http://forums.codeguru.com/archive/index.php/t-514404.html, i.e. calling some_vec.resize(new_size), where N = new_size - some_vec.size() with N >= 2, and VC10 default-constructed all N new elements, whereas GCC default constructed a single element, as the prototype element, to copy-construct it N times for the new elements.

Since this is a vector of uuid, where the default-constructor randomly initializes each new instance, we ended up with N times the same uuid with GCC and N different uuids with VC. That was enough to wreak havoc in our test suite on one platform but not another, and was no fun to find.

My question is thus: who is right? VC or GCC? Or is this one of those beloved corners of C++ that's unspecified? TIA, --DD

ddevienne
  • 1,802
  • 2
  • 17
  • 28
  • 1
    The standard has changed. Here is a similar question [std::vector, default construction, C++11 and breaking changes](http://stackoverflow.com/questions/5759232/stdvector-default-construction-c11-and-breaking-changes) – Bo Persson Jul 30 '12 at 14:23
  • It should be noted that your class is a bit "weird": Basically, you have the situation where for `T x; T y;` you have `x != y`. This warrants a lot of extra care, and explicit documentation... – Kerrek SB Jul 30 '12 at 14:25
  • Randomization on construction is a bad thing, you can see it in your example. Most code assumes that all default constructed objects are equal. To solve these problems you should have a randomizing function. Or a factory that creates randomized objects. – Daniel Jul 30 '12 at 14:26
  • Thank you all for the lightning fast answers. Indeed we are in C++03 on GCC, and leave VC10 in its C++11 default mode. Yes, our uid class could have default-constructed to a null/zero uid, but I was not there in september 2003 when it was introduced. – ddevienne Jul 30 '12 at 14:35

1 Answers1

6

I bet if you compile GCC with -std=c++0x, you'll get the same result as with MSVC, that is, the N default constructions. This has changed in C++11, see here. There are now two overloads, one with just the new size that default constructs the new elements, and another that takes a "prototype" parameter to copy-construct every new element from.

Now, to get consistent results no matter what mode you compile in, just use

v.resize(new_size, T());

Background info: The change was necessary, since there are now types that can be movable, but not copyable (like std::unique_ptr). The old signature demanded copyability. Now the first template parameter to standard container types is only required to be copyable, if you use operations that require a copy.

Xeo
  • 129,499
  • 52
  • 291
  • 397