12

In other words is the following code sound(defined behavior,portable,...)

   std::vector<int> vec(100,42);
   std::vector<int> other = std::move(vec);
   vec.resize(0);//is this sound

   //using vec like an empty vector
R Sahu
  • 204,454
  • 14
  • 159
  • 270
user1235183
  • 3,002
  • 1
  • 27
  • 66
  • 2
    You can do *anything* with that `vector` that does not expect any particular properties (beyond validity). I'd prefer `clear()` over `resize(0)`, though. – Walter Jun 07 '16 at 16:07

2 Answers2

10

Yes, it is safe.

From §23.3.6.5:

If sz <= size(), equivalent to calling pop_back() size() - sz times. If size() < sz, appends sz - size() default-inserted elements to the sequence.

So basically, when you call resize(0), it calls pop_back() until every element is removed from the vector.

It doesn't matter that you moved vec, because even though the state of vec is unspecified, it is still a valid vector that you can modify.

So, the std::vector will be empty after a call to resize(0).

Rakete1111
  • 47,013
  • 16
  • 123
  • 162
  • 3
    No, you can't call `pop_back()`, because `pop_back()` has preconditions. However, `size()` does not, and once you've called `size()`, and ensured it is greater than 0, you've checked that the vector satisfies the preconditions of `pop_back()`, and so it is then safe to call it. – Benjamin Lindley Jun 07 '16 at 16:16
  • 4
    [FYI] It is a [defect](http://wg21.cmeerw.net/lwg/issue2160) to define `resize` in terms of `pop_back`. – NathanOliver Jun 07 '16 at 16:26
5

After having moved from an object, you can generally not make any assumptions about the object's state. That means that you can only call member functions that do not have any preconditions. Happily, std::vector::resize does not have value-dependent preconditions, so you can call resize on a moved-from vector.

Kerrek SB
  • 464,522
  • 92
  • 875
  • 1,084
  • *you can generally not make any assumptions about the object's state* **wrong**: you can assume it's valid. That's the whole point. – Walter Jun 07 '16 at 16:09
  • As for the preconditions mentioned for resize. §23.3.6.3 : 13 *Requires: T shall be MoveInsertable and DefaultInsertable into *this.* – Captain Giraffe Jun 07 '16 at 16:16
  • 4
    @Walter: That goes without saying. Every object is valid. Otherwise it's not an object. – Kerrek SB Jun 07 '16 at 16:19
  • @CaptainGiraffe: Yes. That's not value-dependent; that depends only on the *type*. So it doesn't relate to whether you've moved from a container. – Kerrek SB Jun 07 '16 at 16:19
  • @KerrekSB I should have been explicit about the conclusion. Your comment clarifies the intent of mine, thanks – Captain Giraffe Jun 07 '16 at 16:22
  • @KerrekSB that is flat-out wrong, if the move garbled the vector's members instead of marking it as empty (or whatever), it would not be in a valid state. moving objects must leave the moved object in a valid state. – kmdreko Jun 07 '16 at 16:26
  • 1
    @vu1p3n0x: Such an object would not be destructible, and the destructor, too, has no value-dependent preconditions. – Kerrek SB Jun 07 '16 at 16:36
  • @KerrekSB Well, this was exactly the point of the question: is the object in a valid state (such that `resize(0)` can be called)? And, of course, it has to be. Since 'valid state' and 'destructible' are two different things, this was apparently not obvious to the user. *Otherwise it's not an object* -- nonsense: an object can be in an invalid state (put there by buggy code, e.g. via a race condition). – Walter Jun 07 '16 at 16:46
  • 2
    @Walter: I get your point, of course, and I know about the much quoted "valid but unspecified". But I'd like to make a point that the move construction and assignment are just normal member functions, and they aren't special in any way that diverges from existing conventions and design, and there is nothing that needs to be explicitly called out. The takeaway is that "unspecified state" means "may not satisfy any preconditions". – Kerrek SB Jun 07 '16 at 16:51