10

I do realize is_pod is a sufficient condition for a type to be memcpy-able, but is has_trivial_destructor also sufficient for this purpose? If not, why?

Jonas
  • 121,568
  • 97
  • 310
  • 388
user541686
  • 205,094
  • 128
  • 528
  • 886

4 Answers4

22

No. The requirement is that the type be trivially copyable (§3.9/2) which has a few more requirements, like the lack of a non-trivial copy constructor (§9/6).

A trivially copyable class is a class that:

— has no non-trivial copy constructors (12.8),

— has no non-trivial move constructors (12.8),

— has no non-trivial copy assignment operators (13.5.3, 12.8),

— has no non-trivial move assignment operators (13.5.3, 12.8), and

— has a trivial destructor (12.4).

So you should use is_trivially_copyable instead.

Community
  • 1
  • 1
R. Martinho Fernandes
  • 228,013
  • 71
  • 433
  • 510
  • 1
    `is_trivially_copyable` doesn't seem to be widely documented, do you have a reference? **Never mind**, found it here: http://en.cppreference.com/w/cpp/types/is_trivially_copyable – Mark Ransom Aug 16 '12 at 00:42
  • 1
    @MarkRansom: Table 49 in the most recent draft, §20.9.4.3. – GManNickG Aug 16 '12 at 00:44
  • I propose to check for `is_copy_constructible` in addition, because that catches deleted copy constructors. I feel like that while private trivial copy ctors may make sense to be undermined by "memcpy" (after all it may be the author of the class that memcpy's them), a deleted trivial copy ctor doesn't make sense to be undermined by "memcpy" IMHO. Trying to "memcpy" them as a more optimized version of algorithms such as "std::copy" should fail for deleted copy ctors IMHO. – Johannes Schaub - litb Aug 18 '12 at 20:15
9

It is not sufficient that an object has a trivial destructor. It also needs to have trivial copy operations. The object may maintain pointers to internal buffers, for example. There is no need to destroy anything but copying would need to set up the pointers in the copied to object because they would otherwise point into the buffer of the source object.

Dietmar Kühl
  • 150,225
  • 13
  • 225
  • 380
5

Although it's generally rare in practice, there may be a situation where a class has a non-trivial copy constructor, along with a trivial destructor. Consider a class with a static member variable that just counts how many times the class has been copied. If you memcpy it, the counter would be inaccurate.

Charles Salvia
  • 52,325
  • 13
  • 128
  • 140
  • 1
    On a side note, the standard clearly states that you should not depend on side effects from copy constructors, as copies might be performed or elided in different circumstances, so the accuracy of such a counter would be limited at best. – David Rodríguez - dribeas Aug 16 '12 at 02:45
  • @DavidRodríguez-dribeas: Copies may be elided, but if they are, they have to be completely elided. I.e. such a copy counter will be updated if and only if a copy was actually made. This is of course essential for classes like `shared_ptr<>`. The compiler may elide copies of a `shared_ptr`, but this will not cause memory leaks. – MSalters Aug 16 '12 at 08:08
  • @MSalters: I am not saying that it would be safe, just that such a counter would be *imprecise* by definition. – David Rodríguez - dribeas Aug 16 '12 at 12:20
0

It seems to me that a class with a plain pointer would qualify as has_trivial_destructor, but you usually want to make a deep copy whereas memcpy would create a shallow copy.

Mark Ransom
  • 299,747
  • 42
  • 398
  • 622
  • 2
    Well, if the class is trivially destructible it would need to break the rule of three to have a deep-copying copy-constructor. :) That said, I think the question is asking about undefined behavior, i.e. if `is_trivially_destructible::value` is `true`, then `memcpy`ing a `T` is well-defined. – GManNickG Aug 16 '12 at 00:42