0

Cppreference states, regarding std::memcpy() (emphasis added):

If the objects are potentially-overlapping or not TriviallyCopyable, the behavior of memcpy is not specified and may be undefined.

So, I always check to ensure an object IS trivially-copyable before using memcpy(), like this:

#include <type_traits>

static_assert(std::is_trivially_copyable<T>::value, "Type T must "
    "be a trivially-copyable type in order to guarantee that `memcpy()` is safe "
    "to use on it.");
memcpy(&outputData, &data, sizeof(data));

std::copy(), however, doesn't seem to have this limitation: https://en.cppreference.com/w/cpp/algorithm/copy.

Does this limitation that the type must be trivially-copyable to not have undefined behavior NOT apply to std::copy()?

Also, I just realized in my "placement new" answer here, which made me wonder about this whole thing, I used just memcpy() instead of std::memcpy(), and I was not using namespace std;, so which function was called? Is memcpy() a different implementation from std::memcpy()?

Gabriel Staples
  • 36,492
  • 15
  • 194
  • 265
  • `std::copy` only has the requirements it says it does. – Mooing Duck Sep 16 '20 at 01:32
  • Yeah but that's a community wiki, not a C++ standards manual...heck, I edit that wiki on occasion, but I don't even have a standards manual. (Point of my comment: it may be an incomplete wiki, and perhaps this very question will cause someone to update that wiki in case it's lacking information). – Gabriel Staples Sep 16 '20 at 01:34
  • 2
    The real Standard costs money to produce so they charge for it. Fortunately they are quite liberal with detailed drafts.: http://eel.is/c++draft/ I used to have a chart somewhere that mapped draft revision numbers that were closest to the approve dStandards, but I've misplaced it. – user4581301 Sep 16 '20 at 01:37
  • 2
    Here's the section on std::copy: http://eel.is/c++draft/alg.copy – user4581301 Sep 16 '20 at 01:44
  • 2
    `memcpy()` copies *raw memory*, so it is undefined for non-trivial data. `std::copy()` copies *elements* and works for complex types that support copy semantics. If the data is trivial, `std::copy()` will use `memcpy()` internally – Remy Lebeau Sep 16 '20 at 02:29

2 Answers2

4

memcpy is a function that copies bytes. std::copy copies objects. In some cases, copying the bytes of an object can copy the object.

But these are not the same thing. std::copy sees bytewise copying of memory as a potential optimization under certain circumstances in pursuit of its goal: copying objects. It's an implementation detail. For memcpy, bytewise copying is what it does; that bytewise copying can sometimes copy an object is maybe a side benefit.

It should also be noted that std::copy operates on generic iterators. It can "copy" into a ofstream via a proper ostream_iterator, or it can copy from an ifstream via an istream_iterator. std::copy is not fussy about the source or destination. By contrast, memcpy requires that you're copying from and to a contiguous sequence of bytes (and that these sequences are disjoint).

Nicol Bolas
  • 449,505
  • 63
  • 781
  • 982
  • 1
    Notable: `std::copy(std::istream_iterator(std::cin), {}, std::ostrream_iterator(std::cout));` will just directly copy `cin` to `cout`. – Mooing Duck Sep 16 '20 at 16:00
3
  1. std::copy is a simple standard algorithm. Its general version just uses assignment in a loop, so it is applicable in the same cases as assignment. Library implementers will usually have a special implementation of std::copy through memcpy when it is safe to do so and is faster than assignment. Since memcpy is a legacy C function, it should almost never be used in C++ outside low-level libraries,.

  2. ::memcpy and std::memcpy is really the same thing, because it is coming from C standard library. Formally, you should use ::memcpy if you #include <string.h> and std::memcpy if you #include <cstring>, but in practice ::memcpy is always available.

Eugene
  • 6,194
  • 1
  • 20
  • 31