https://gcc.gnu.org/bugzilla/show_bug.cgi?id=68350
Arthur O'Dwyer <arthur.j.odwyer at gmail dot com> changed: What |Removed |Added ---------------------------------------------------------------------------- CC| |arthur.j.odwyer at gmail dot com --- Comment #6 from Arthur O'Dwyer <arthur.j.odwyer at gmail dot com> --- (I got here from https://stackoverflow.com/questions/47464819/uninitialized-copy-memcpy-memmove-optimization) Jonathan, you wrote: > The point of the condition is to decide whether to use std::copy, because for > trivially-copyable types that is optimized to memmove. But unlike > std::uninitialized_copy, std::copy calls no constructors, so the type must be > trivially default constructible, and if an exception is thrown, it calls no > destructors, so the type must be trivially destructible as well. So we can > only use the memmove optimization for types which [...] What do you mean "if an exception is thrown"? If we call std::copy from here, then it's because we are taking the memmove path. memmove never throws exceptions, so how can we be worried about what happens "if an exception is thrown"? That is, the following code 100% definitely never attempts to destroy a `B` object, so why does it matter that `B`'s destructor is non-trivial? // https://godbolt.org/z/w7nTe5 struct A { int i; A() = default; A(const A&) = default; ~A() = default; }; struct B { int i; B() = default; B(const B&) = default; ~B() {} }; void copyAs(A *p, A *q, int n) { std::uninitialized_copy(p, p+n, q); // successfully uses memmove } void copyBs(B *p, B *q, int n) { std::uninitialized_copy(p, p+n, q); // fails to use memmove }