Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

Isn't the example with re-using a moved c++ vector completely safe?

    std::vector<int> x = {1, 2, 3};
    process(std::move(x));
    x.push_back(4);
    // Runtime invalid memory access


Oh, I didn't know about this one. I did some search, and looks like it should be "valid but unspecified state" after move?

I can't think of any case that relying on unspecified state is desirable even if it's valid, though I guess it's better if I change that to x.pop_back(); to be clear.

Please let me know if my understanding is incorrect and thanks for the information!


The only thing 'unspecified' guarantees you in this context is 'safe to destroy'. It specifically does not guarantee the safety of any other member functions - only the destructor. So either push_back() or pop_back() could potentially cause UB here (specifically, it's quite possible that the move swaps some internal pointers for nullptr, so you end up dereferencing null here - but morally, it's just never okay to continue using a moved-from object).


The vector is "valid" and that is what carries all the weight here. The vector is still a vector.

push_back is absolutely defined. pop_back might be undefined, because pop_back is UB on an empty vector. If you like, call clear, and be assured of an empty, reusable vector. It's not idiomatic, but it's safe.


A moved-from std::vector<int> will always be empty. However, a moved-from std::vector<int, custom_stateful_allocator> may not be.

Howard Hinnant had a Stack Overflow reply a while back going through the possible corner cases of this precise question: https://stackoverflow.com/a/17735913


Yes, it's completely safe and its rust equivalent is

    let x = vec![1, 2, 3];
    process(std::mem::replace(&mut x, Vec::new()));
    x.push(4);
https://doc.rust-lang.org/std/mem/fn.replace.html


There's no guarantee that std::move moves elements out of x. (and thus no guarantee that it's equivalent to a Rust mem::replace with a new Vec) The only requirement the C++ standard imposes is that the vector is left in a "valid but unspecified state".


It’s runtime safe (I’m taking your word for it). In Rust this would be a compile time error.

Although, are any C++ compilers able to at least issue a warning in this case? It wouldn’t surprise me if they could.


Move constructors are allowed to call the moved object's destructor.

Not necessarily like the example given, but

  Object a {std::move(x)};
  x.push_back(4);
could/should segfault.


No, move constructors are never allowed to call the moved-from argument's destructor. Ever.

Sometimes the compiler calls that destructor after it has finished the move, if the thing is no longer in scope. That should not be confused with a thing happening in the constructor.


Yes it is safe.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: