Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why "move semantics" rather than simply memcpy?

Tags:

c++

c++11

c++17

Given the following code:

typename std::aligned_storage<sizeof(T), alignof(T)>::type storage_t;

//this moves the back of src to the back of dst:
void push_popped(std::list<storage_t> & dstLst, std::list<storage_t> & srcLst)
{
  auto & src = srcLst.back();
  dstLst.push_back(storage_t());
  auto & dst = dstLst.back();
  std::memcpy(&dst, &src, sizeof(T));
  srcLst.pop_back();
}

I'm aware of 3 reasons why this approach is not, in general, correct (even though it avoids calling src->~T() and so avoids double-reclamation of T's resources).

  1. object members of type U* that point to other U members of the same object
  2. hidden class members may need to be updated (vtable, for instance)
  3. the system needs to record that no T exists anymore at src and that a T does now exist at dst

(These are mentioned here: http://www.gamedev.net/topic/655730-c-stdmove-vs-stdmemcpy/#entry5148523.)

Assuming that T is not a type whose memory address is a property of its state (std::mutex or std::condition_variable, for instance), are these the only issues with this approach? Or are there other things that could go wrong? I'd like a description of the unknown issues.

I'd like to think I have an "object relocation semantics" developed, but I'd rather not ask people to consider it if there's an obvious hole in it.

like image 550
B Simpson Avatar asked Feb 09 '23 03:02

B Simpson


1 Answers

The concept of "trivially copyable" implies that a memcpy is safe. You can test if a type is trivially copyable via a trait in std.

It includes the idea that destroying it is a noop; in your case, you want destruction to not be a noop, but rather not done on the source, while being done on the dest.

The concept of "move-and-destroy-source" has been proposed in the C++1z standardization process independent of the "trivially copyable" concept. It was proposed for exception safety; there are types for which a move-construct is not exception-safe, but a move-construct-and-destroy-source would be. And there are thorny problems involving exceptions and container allocations that make a noexcept move-ctor operation very valuable.

If that gets into the standard, then a trivially-copyable-if-you-don't-destroy-source concept could also be added to the standard, if it proves valuable.

It wouldn't apply to everything move semantics can enhance, and it may require effort on the part of programmers (how the compiler can work out that "it is ok to elide a destroyer" is not going to be easy; all non-trivial non-structural properties of Turing Machine behavior are intractable.)

like image 173
Yakk - Adam Nevraumont Avatar answered Feb 19 '23 00:02

Yakk - Adam Nevraumont