It is my understanding that move semantics can use move-constructors to elide what would otherwise be a copy. For example, a function returning a (perhaps) large data structure can now return by value, and the move constructor will be used to avoid a copy.
My question is this: is the compiler required to not copy when this is possible? It doesn't seem to be the case. In that case, wouldn't the following code have "implementation-defined" semantics?
static const int INVALID_HANDLE = 0xFFFFFFFF;
class HandleHolder {
int m_handle;
public:
explicit HandleHolder(int handle) : m_handle(handle) {}
HandleHolder(HandleHolder& hh) {
m_handle = hh.m_handle;
}
HandleHolder(HandleHolder&& hh) : m_handle(INVALID_HANDLE) {
swap(m_handle, hh.m_handle);
}
~HandleHolder() noexcept {
if (m_handle != INVALID_HANDLE) {
destroy_the_handle_object(m_handle);
}
}
};
Say then we make a function:
HandleHolder make_hh(int handle) { return HandleHolder(handle); }
Which constructor is called? I would expect the move constructor, but am I guaranteed the move constructor?
I'm aware this is a silly example and that -- for example -- the copy constructor of this object should be deleted because there is no way to use it safely otherwise, but the semantics are simple enough that I wouldn't think something like this would be implementation-defined.
Aucun commentaire:
Enregistrer un commentaire