Will memcpy or memmove cause problems copying classes? - c++

Suppose I have any kind of class or structure. No virtual functions or anything, just some custom constructors, as well as a few pointers that would require cleanup in the destructor.
Would there be any adverse affects to using memcpy or memmove on this structure? Will deleting a moved structure cause problems? The question assumes that the memory alignment is also correct, and we are copying to safe memory.

In the general case, yes, there will be problems. Both memcpy and memmove are bitwise operations with no further semantics. That might not be sufficient to move the object*, and it is clearly not enough to copy.
In the case of the copy it will break as multiple objects will be referring to the same dynamically allocated memory, and more than one destructor will try to release it. Note that solutions like shared_ptr will not help here, as sharing ownership is part of the further semantics that memcpy/memmove don't offer.
For moving, and depending on the type you might get away with it in some cases. But it won't work if the objects hold pointers/references to the elements being moved (including self-references) as the pointers will be bitwise copied (again, no further semantics of copying/moving) and will refer to the old locations.
The general answer is still the same: don't.
* Don't take move here in the exact C++11 sense. I have seen an implementation of the standard library containers that used special tags to enable moving objects while growing buffers through the use of memcpy, but it required explicit annotations in the stored types that marked the objects as safely movable through memcpy, after the objects were placed in the new buffer the old buffer was discarded without calling any destructors (C++11 move requires leaving the object in a destructible state, which cannot be achieved through this hack)

Generally using memcpy on a class based object is not a good idea. The most likely problem would be copying a pointer and then deleting it. You should use a copy constructor or assignment operator instead.

No, don't do this.
If you memcpy a structure whose destructor deletes a pointer within itself, you'l wind up doing a double delete when the second instance of the structure is destroyed in whatever manner.
The C++ idiom is copy constructor for classes and std::copy or any of its friends for copying ranges/sequences/containers.

If you are using C++11, you can use std::is_trivially_copyable to determine if an object can be copied or moved using memcpy or memmove. From the documentation:
Objects of trivially-copyable types are the only C++ objects that may
be safely copied with std::memcpy or serialized to/from binary files
with std::ofstream::write()/std::ifstream::read(). In general, a
trivially copyable type is any type for which the underlying bytes can
be copied to an array of char or unsigned char and into a new object
of the same type, and the resulting object would have the same value
as the original.
Many classes don't fit this description, and you must beware that classes can change. I would suggest that if you are going to use memcpy/memmove on C++ objects, that you somehow protect unwanted usage. For example, if you're implementing a container class, it's easy for the type that the container holds to be modified, such that it is no longer trivially copyable (eg. somebody adds a virtual function). You could do this with a static_assert:
template<typename T>
class MemcopyableArray
{
static_assert(std::is_trivially_copyable<T>::value, "MemcopyableArray used with object type that is not trivially copyable.");
// ...
};

Aside from safety, which is the most important issue as the other answers have already pointed out, there may also be an issue of performance, especially for small objects.
Even for simple POD types, you may discover that doing proper initialization in the initializer list of your copy constructor (or assignments in the assignment operator depending on your usage) is actually faster than even an intrinsic version of memcpy. This may very well be due to memcpy's entry code which may check for word alignment, overlaps, buffer/memory access rights, etc.... In Visual C++ 10.0 and higher, to give you a specific example, you would be surprised by how much preamble code that tests various things executes before memcpy even begins its logical function.

Related

Why doesn't CPP create a default deep-copy constructor?

I don't understand why don't they have a copy constructor which makes a real multiple of the original.
As we know the main problem of the default copy constructor is, that it performs a shallow copy. So that if there is a pointer it would only copy it's address but why doesn't it dereference the pointer a copies the content?
The main problem arises when having a dinamic allocation of memory . So that one can mistakenly delete it while having a pointer pointing to it, that's why we make our own copy constructors and do not use the default one.
But I can't get it, why doesn't CPP do it? Why doesn't it copy the content
As we know the main problem of the default copy constructor is, that it performs a shallow copy.
We don't know that.
that's why we make our own copy constructors and do not use the default one.
In C++ you should almost never write your own copy constructor (the rule of zero).
The main problem arises when having a dinamic allocation of memory . So that one can mistakenly delete it while having a pointer pointing to it
It's a non-problem. Why? Because in C++ we use the concept of RAII and we have tools in the standard library that solved all of the problems you see. In C++ you should never have to write explicit new and you should never have a raw pointer that is a owner. Use standard containers (e.g. std::vector) and smart pointers e.g. (std::unique_ptr).
I don't understand why don't they have a copy constructor which makes a real multiple of the original
Because the compiler doesn't know what the copy-semantics of the object should be. That only the writer of the class knows. You can't know what the semantics of the pointer are. Is is a pointer that uniquely owns the memory resource? If so, was it acquired with malloc, new, new[], or with something else? Does it share its ownership of the memory? Or is it simply pointing to an object it doesn't own? Since you cannot know any of this from the declaration/definition of a class, a compiler simply cannot implement "deep copy" automatically with raw pointers.
Except it does. It does implement deep copy by default, or shallow copy by default, or a combination of them. And it does so correctly. Remember when I told you to not use raw pointers for ownership? Use the appropriate abstractions (containers, smart pointers) and the default copy ctor will do exactly what it needs to do.
As we know the main problem of the default copy constructor is, that it performs a shallow copy.
Shallow copying is not a problem in general. It's only a problem if you want to make a deep copy, have a referential member, and assume the implicit copy constructor to do what you want.
Shallow copying is often useful and typically intentional.
but why doesn't it dereference the pointer a copies the content?
Because where would the copy constructor store the copied object? Where should the pointer member point to?
The compiler cannot read your mind and cannot know whether you want to allocate memory, or how to allocate memory. If the compiler did allocate memory in an implicit function, then who would be responsible for its deletion? If the compiler deleted any pointers implicitly, that would be highly surprising when you intended to have non-owning pointers to something that must not be deleted.
why can't the programmer be responsible for it?
Memory management is difficult enough as it is. At the moment it is at least manageable by following the simple rule: You delete everything that you new. If we introduce implicit allocations and impose the responsibility on the programmer to know of the existence of these implicit allocations, our job would become much harder.
Furthermore, a pointer can have an invalid value. In such cases indirecting through it would have undefined behaviour. And it is impossible to inspect the pointer to find out whether it is invalid. This would make the suggested implicit "deep copying" highly error prone.
Shallow implicit copying is the only sensible choice in a language that has manual memory management. Even in garbage collected languages this is generally the better choice.
that's why we make our own copy constructors and do not use the default one.
We rarely write user declared copy constructors (outside of beginner courses). Those are mostly needed for classes whose sole purpose is to manage memory (or other resources) such as smart pointers. And we rarely need to write those, since the standard library offers the most general smart pointers and data structures out of the box.
we should create our own copy constructor once we have a dynamic memory inside the class
Indeed, if your class manages dynamic memory, then it will need a custom copy constructor. But the typical solution is to not manage dynamic memory inside your class. See the paragraph above. Keep any and all memory allocations and other dynamic resources in a smart pointer or a container.
The compiler has no way of knowing the meaning of the pointers it is supposed to "deep copy".
For example, does a float pointer point to a single float or to a C-style float array? If it is an array, what is the length of the array that it should copy? Please note that I am not talking about C++ style arrays (i.e. std::array).
If you want "deep copying" to be handled automatically, you can use container classes for data members that should be copied.

Copying classes between ranges that might overlap

In C, we have the functions memcpy and memmove to efficiently copy data around. The former yields undefined behavior if the source and destination regions overlap, but the latter is guaranteed to deal with that "as expected," presumably by noticing the direction of overlap and (if necessary) choosing a different algorithm.
The above functions are available in C++ (as std::memcpy and std::memmove), of course, but they don't really work with non-trivial classes. Instead, we get std::copy and std::copy_backward. Each of these works if the source and destination ranges don't overlap; moreover, each is guaranteed to work for one "direction" of overlap.
What can we use if we want to copy from one region to another and we don't know at compile-time if the ranges may overlap or in what direction that overlap may occur? It doesn't seem that we have an option. For general iterators it may be difficult to determine if ranges overlap, so I understand why no solution is provided in that case, but what about when we're dealing with pointers? Ideally, there'd be a function like:
template<class T>
T * copy_either_direction(const T * inputBegin, const T * inputEnd, T * outputBegin) {
if ("outputBegin ∈ [inputBegin, inputEnd)") {
outputBegin += (inputEnd - inputBegin);
std::copy_backward(inputBegin, inputEnd, outputBegin);
return outputBegin;
} else {
return std::copy(inputBegin, inputEnd, outputBegin);
}
}
(A similar function with T * replaced with std::vector<T>::iterator would also be nice. Even better would be if this were guaranteed to work if inputBegin == outputBegin, but that's a separate gripe of mine.)
Unfortunately, I don't see a sensible way to write the condition in the if statement, as comparing pointers into separate blocks of memory often yields undefined behavior. On the other hand, the implementation clearly has its own way to do this, as std::memmove inherently requires one. Thus, any implementation could provide such a function, thereby filling a need that the programmer simply can't. Since std::memmove was considered useful, why not copy_either_direction? Is there a solution I'm missing?
memmove works because it traffics in pointers to contiguous bytes, so the ranges of the two blocks to be copied are well defined. copy and move take iterators that don't necessarily point at contiguous ranges. For example, a list iterator can jump around in memory; there's no range that the code can look at, and no meaningful notion of overlap.
I recently learned that std::less is specialized for pointers in a way that provides a total order, presumably to allow one to store pointers in std::sets and related classes. Assuming that this must agree with the standard ordering whenever the latter is defined, I think the following will work:
#include <functional>
template<class T>
T * copy_either_direction(const T * inputBegin, const T * inputEnd, T * outputBegin) {
if (std::less<const T *>()(inputBegin, outputBegin)) {
outputBegin += (inputEnd - inputBegin);
std::copy_backward(inputBegin, inputEnd, outputBegin);
return outputBegin;
} else {
return std::copy(inputBegin, inputEnd, outputBegin);
}
}
What can we use if we want to copy from one region to another and we don't know at compile-time if the ranges may overlap or in what direction that overlap may occur?
This is not a logically consistent concept.
After a copy operation, you will have two objects. And each object is defined by a separate and distinct region of memory. You cannot have objects which overlap in this way (you can have subobjects, but an object type cannot be its own subobject). And therefore, it is impossible to copy an object on top of part of itself.
To move an object on top of itself is also not logically consistent. Why? Because moving is a fiction in C++; after the move, you still have two perfectly functional objects. A move operation is merely a destructive copy, one that steals resources owned by the other object. It is still there, and it is still a viable object.
And since an object cannot overlap with another object, it is again impossible.
Trivially copyable types get around this because they are just blocks of bits, with no destructors or specialized copy operations. So their lifetime is not as rigid as that of others. A non-trivially copyable type cannot do this because:
The experience with memmove suggests that there could be a solution in this case (and perhaps also for iterators into contiguous containers).
This is neither possible nor generally desirable for types which are not trivially copyable in C++.
The rules for trivial copyability are that the type has no non-trivial copy/move constructors/assignment operators, as well as no non-trivial destructor. A trivial copy/move constructor/assignment is nothing more than a memcpy, and a trivial destructor does nothing. And therefore, these rules effectively ensures that the type is nothing more than a "block of bits". And one "block of bits" is no different from another, so copying it via memmove is a legal construct.
If a type has a real destructor, then the type is maintaining some sort of invariant that requires actual effort to maintain. It may free up a pointer or release a file handle or whatever. Given that, it makes no sense to copy the bits, because now you have two objects that reference the same pointer/file handle. That's a bad thing to do, because the class will generally want to control how that gets handled.
There is no way to solve this problem without the class itself being involved in the copy operation. Different class have different behavior with respect to managing their internals. Indeed, that is the entire purpose of objects having copy constructors and assignment operators. So that a class can decide for itself how to maintain the sanity of its own state.
And it doesn't even have to be a pointer or file handle. Maybe each class instance has a unique identifier; such a value is generated at construction time, and it never gets copied (new copies get new values). For you to violate such a restriction with memmove leaves your program in an indeterminate state, because you will have code that expects such identifiers to be unique.
That's why memmoveing for non-trivially copyable types yields undefined behavior.

Can we say bye to copy constructors?

Copy constructors were traditionally ubiquitous in C++ programs. However, I'm doubting whether there's a good reason to that since C++11.
Even when the program logic didn't need copying objects, copy constructors (usu. default) were often included for the sole purpose of object reallocation. Without a copy constructor, you couldn't store objects in a std::vector or even return an object from a function.
However, since C++11, move constructors have been responsible for object reallocation.
Another use case for copy constructors was, simply, making clones of objects. However, I'm quite convinced that a .copy() or .clone() method is better suited for that role than a copy constructor because...
Copying objects isn't really commonplace. Certainly it's sometimes necessary for an object's interface to contain a "make a duplicate of yourself" method, but only sometimes. And when it is the case, explicit is better than implicit.
Sometimes an object could expose several different .copy()-like methods, because in different contexts the copy might need to be created differently (e.g. shallower or deeper).
In some contexts, we'd want the .copy() methods to do non-trivial things related to program logic (increment some counter, or perhaps generate a new unique name for the copy). I wouldn't accept any code that has non-obvious logic in a copy constructor.
Last but not least, a .copy() method can be virtual if needed, allowing to solve the problem of slicing.
The only cases where I'd actually want to use a copy constructor are:
RAII handles of copiable resources (quite obviously)
Structures that are intended to be used like built-in types, like math vectors or matrices -
simply because they are copied often and vec3 b = a.copy() is too verbose.
Side note: I've considered the fact that copy constructor is needed for CAS, but CAS is needed for operator=(const T&) which I consider redundant basing on the exact same reasoning;
.copy() + operator=(T&&) = default would be preferred if you really need this.)
For me, that's quite enough incentive to use T(const T&) = delete everywhere by default and provide a .copy() method when needed. (Perhaps also a private T(const T&) = default just to be able to write copy() or virtual copy() without boilerplate.)
Q: Is the above reasoning correct or am I missing any good reasons why logic objects actually need or somehow benefit from copy constructors?
Specifically, am I correct in that move constructors took over the responsibility of object reallocation in C++11 completely? I'm using "reallocation" informally for all the situations when an object needs to be moved someplace else in the memory without altering its state.
The problem is what is the word "object" referring to.
If objects are the resources that variables refers to (like in java or in C++ through pointers, using classical OOP paradigms) every "copy between variables" is a "sharing", and if single ownership is imposed, "sharing" becomes "moving".
If objects are the variables themselves, since each variables has to have its own history, you cannot "move" if you cannot / don't want to impose the destruction of a value in favor of another.
Cosider for example std::strings:
std::string a="Aa";
std::string b=a;
...
b = "Bb";
Do you expect the value of a to change, or that code to don't compile? If not, then copy is needed.
Now consider this:
std::string a="Aa";
std::string b=std::move(a);
...
b = "Bb";
Now a is left empty, since its value (better, the dynamic memory that contains it) had been "moved" to b. The value of b is then chaged, and the old "Aa" discarded.
In essence, move works only if explicitly called or if the right argument is "temporary", like in
a = b+c;
where the resource hold by the return of operator+ is clearly not needed after the assignment, hence moving it to a, rather than copy it in another a's held place and delete it is more effective.
Move and copy are two different things. Move is not "THE replacement for copy". It an more efficient way to avoid copy only in all the cases when an object is not required to generate a clone of itself.
Short anwer
Is the above reasoning correct or am I missing any good reasons why logic objects actually need or somehow benefit from copy constructors?
Automatically generated copy constructors are a great benefit in separating resource management from program logic; classes implementing logic do not need to worry about allocating, freeing or copying resources at all.
In my opinion, any replacement would need to do the same, and doing that for named functions feels a bit weird.
Long answer
When considering copy semantics, it's useful to divide types into four categories:
Primitive types, with semantics defined by the language;
Resource management (or RAII) types, with special requirements;
Aggregate types, which simply copy each member;
Polymorphic types.
Primitive types are what they are, so they are beyond the scope of the question; I'm assuming that a radical change to the language, breaking decades of legacy code, won't happen. Polymorphic types can't be copied (while maintaining the dynamic type) without user-defined virtual functions or RTTI shenanigans, so they are also beyond the scope of the question.
So the proposal is: mandate that RAII and aggregate types implement a named function, rather than a copy constructor, if they should be copied.
This makes little difference to RAII types; they just need to declare a differently-named copy function, and users just need to be slightly more verbose.
However, in the current world, aggregate types do not need to declare an explicit copy constructor at all; one will be generated automatically to copy all the members, or deleted if any are uncopyable. This ensures that, as long as all the member types are correctly copyable, so is the aggregate.
In your world, there are two possibilities:
Either the language knows about your copy-function, and can automatically generate one (perhaps only if explicitly requested, i.e. T copy() = default;, since you want explicitness). In my opinion, automatically generating named functions based on the same named function in other types feels more like magic than the current scheme of generating "language elements" (constructors and operator overloads), but perhaps that's just my prejudice speaking.
Or it's left to the user to correctly implement copying semantics for aggregates. This is error-prone (since you could add a member and forget to update the function), and breaks the current clean separation between resource management and program logic.
And to address the points you make in favour:
Copying (non-polymorphic) objects is commonplace, although as you say it's less common now that they can be moved when possible. It's just your opinion that "explicit is better" or that T a(b); is less explicit than T a(b.copy());
Agreed, if an object doesn't have clearly defined copy semantics, then it should have named functions to cover whatever options it offers. I don't see how that affects how normal objects should be copied.
I've no idea why you think that a copy constructor shouldn't be allowed to do things that a named function could, as long as they are part of the defined copy semantics. You argue that copy constructors shouldn't be used because of artificial restrictions that you place on them yourself.
Copying polymorphic objects is an entirely different kettle of fish. Forcing all types to use named functions just because polymorphic ones must won't give the consistency you seem to be arguing for, since the return types would have to be different. Polymorphic copies will need to be dynamically allocated and returned by pointer; non-polymorphic copies should be returned by value. In my opinion, there is little value in making these different operations look similar without being interchangable.
One case where copy constructors come in useful is when implementing the strong exception guarantees.
To illustrate the point, let's consider the resize function of std::vector. The function might be implemented roughly as follows:
void std::vector::resize(std::size_t n)
{
if (n > capacity())
{
T *newData = new T [n];
for (std::size_t i = 0; i < capacity(); i++)
newData[i] = std::move(m_data[i]);
delete[] m_data;
m_data = newData;
}
else
{ /* ... */ }
}
If the resize function were to have a strong exception guarantee we need to ensure that, if an exception is thrown, the state of the std::vector before the resize() call is preserved.
If T has no move constructor, then we will default to the copy constructor. In this case, if the copy constructor throws an exception, we can still provide strong exception guarantee: we simply delete the newData array and no harm to the std::vector has been done.
However, if we were using the move constructor of T and it threw an exception, then we have a bunch of Ts that were moved into the newData array. Rolling this operation back isn't straight-forward: if we try to move them back into the m_data array the move constructor of T may throw an exception again!
To resolve this issue we have the std::move_if_noexcept function. This function will use the move constructor of T if it is marked as noexcept, otherwise the copy constructor will be used. This allows us to implement std::vector::resize in such a way as to provide a strong exception guarantee.
For completeness, I should mention that C++11 std::vector::resize does not provide a strong exception guarantee in all cases. According to www.cplusplus.com we have the the follow guarantees:
If n is less than or equal to the size of the container, the function never throws exceptions (no-throw guarantee).
If n is greater and a reallocation happens, there are no changes in the container in case of exception (strong guarantee) if the type of the elements is either copyable or no-throw moveable.
Otherwise, if an exception is thrown, the container is left with a valid state (basic guarantee).
Here's the thing. Moving is the new default- the new minimum requirement. But copying is still often a useful and convenient operation.
Nobody should bend over backwards to offer a copy constructor anymore. But it is still useful for your users to have copyability if you can offer it simply.
I would not ditch copy constructors any time soon, but I admit that for my own types, I only add them when it becomes clear I need them- not immediately. So far this is very, very few types.

Using memcpy in the STL

Why does C++'s vector class call copy constructors? Why doesn't it just memcpy the underlying data? Wouldn't that be a lot faster, and remove half of the need for move semantics?
I can't imagine a use case where this would be worse, but then again, maybe it's just because I'm being quite unimaginative.
Because the object needs to be notified that it is being moved. For example, there could be pointers to that given object that need to be fixed because the object is being copied. Or the reference count on a reference counted smart pointer might need to be updated. Or....
If you just memcpy'd the underlying memory, then you'd end up calling the destructor twice on the same object, which is also bad. What if the destructor controls something like an OS file handle?
EDIT: To sum up the above:
The copy constructor and destructor can have side effects. Those side effects need to be preserved.
You can safely memcpy POD and built-in types. Those are defined to have no semantics beyond being a bag of bits with respect to memory.
Types that have constructors and destructors, however, must be constructed and destructed in order to maintain invariants. While you may be able to create types that can be memcpy'd and have constructors, it is very difficult to express that in the type signature. So instead of possibly violating invariants associated with all types that have constructors and/or destructors, STL errs on the side of instead maintaining invariants by using the copy constructor when necessary.
This is why C++0x added move semantics via rvalue references. It means that STL containers can take advantage of types that provide a move constructor and give the compiler enough information to optimize out otherwise expensive construction.

unique_ptr - major improvement?

In the actual C++ standard, creating collections satisfying following rules is hard if not impossible:
exception safety,
cheap internal operations (in actual STL containers: the operations are copies),
automatic memory management.
To satisfy (1), a collection can't store raw pointers. To satisfy (2), a collection must store raw pointers. To satisfy (3), a collection must store objects by value.
Conclusion: the three items conflict with each other.
Item (2) will not be satisfied when shared_ptrs are used because when a collection will need to move an element, it will need to make two calls: to a constructor and to a destructor. No massive, memcpy()-like copy/move operations are possible.
Am I correct that the described problem will be solved by unique_ptr and std::move()? Collections utilizing the tools will be able to satisfy all 3 conditions:
When a collection will be deleted as a side effect of an exception, it will call unique_ptr's destructors. No memory leak.
unique_ptr does not need any extra space for reference counter; therefore its body should be exact the same size, as wrapped pointer,
I am not sure, but it looks like this allows to move groups of unique_ptrs by using memmove() like operations (?),
even if it's not possible, the std::move() operator will allow to move each unique_ptr object without making the constructor/destructor pair calls.
unique_ptr will have exclusive ownership of given memory. No accidental memory leaks will be possible.
Is this true? What are other advantages of using unique_ptr?
I agree entirely. There's at last a natural way of handling heap allocated objects.
In answer to:
I am not sure, but it looks like this allows to move groups of unique_ptrs by using memmove() like operations,
there was a proposal to allow this, but it hasn't made it into the C++11 Standard.
Yes, you are right. I would only add this is possible thanks to r-value references.
When a collection will be deleted as a side effect of an exception, it will call unique_ptr's destructors. No memory leak.
Yes, a container of unique_ptr will satisfy this.
unique_ptr does not need any extra space for reference counter; therefore its body should be exact the same size, as wrapped pointer
unique_ptr's size is implementation-defined. While all reasonable implementations of unique_ptr using it's default destructor will likely only be a pointer in size, there is no guarantee of this in the standard.
I am not sure, but it looks like this allows to move groups of unique_ptrs by using memmove() like operations (?),
Absolutely not. unique_ptr is not a trivial class; therefore, it cannot be memmoved around. Even if it were, you can't just memmove them, because the destructors for the originals need to be called. It would have to be a memmove followed by a memset.
even if it's not possible, the std::move() operator will allow to move each unique_ptr object without making the constructor/destructor pair calls.
Also incorrect. Movement does not make constructors and destructors not be called. The unique_ptr's that are being destroyed need to be destroyed; that requires a call to their destructors. Similarly, the new unique_ptrs need to have their constructors called; that's how an object's lifetime begins.
There's no avoiding that; it's how C++ works.
However, that's not what you should be worried about. Honestly, if you're concerned about a simple constructor/destructor call, you're either in code that you should be hand-optimizing (and thus writing your own code for), or you're prematurely optimizing your code. What matters is not whether constructors/destructors are called; what matters is how fast the resulting code is.
unique_ptr will have exclusive ownership of given memory. No accidental memory leaks will be possible.
Yes, it will.
Personally, I'd say you're doing one of the following:
Being excessively paranoid about copying objects. This is evidence by the fact that you consider putting a shared_ptr in a container is too costly of a copy. This is an all-too-common malady among C++ programmers. That's not to say that copying is always good or something, but obsessing over copying a shared_ptr in a container is ridiculous outside of exceptional circumstances.
Not aware of how to properly use move semantics. If your objects are expensive to copy but cheap to move... then move them into the container. There's no reason to have a pointer indirection when your objects already contain pointer indirections. Just use movement with the objects themselves, not unique_ptrs to objects.
Disregarding the alternatives. Namely, Boost's pointer containers. They seem to have everything you want. They own pointers to their objects, but externally they have value semantics rather than pointer semantics. They're exception safe, and any copying happens with pointers. No unique_ptr constructor/destructor "overhead".
It looks like the three conditions I've enumerated in my post are possible to obtain by using Boost Pointer Container Library.
This question illlustrates why I so love the Boehm garbage collector (libgc). There's never a need to copy anything for reasons of memory management, and indeed, ownership of memory no longer needs to be mentioned as part of APIs. You have to buy a little more RAM to get the same CPU performance, but you save hundreds of hours of programmers' time. You decide.