The Fallback Mechanism
Yes, std::move on a const object will trigger a fallback to the copy constructor if no const T&& overload exists. This occurs because std::move is not a move operation itself, but a cast to an rvalue reference. When applied to a const T, it produces a const T&&.
Since a standard move constructor is defined as T(T&& arg), it requires a non-const reference to modify the source object (e.g., nulling out a pointer). A const T&& cannot bind to a non-const T&&. However, it can bind to a const T&, which is the signature of the copy constructor. Consequently, the compiler selects the copy constructor as the best viable match.
Performance Implications in Generic Code
The primary implication is a silent performance degradation. In generic or template-heavy code, developers often use std::move to ensure efficiency regardless of the specific type. When the underlying type is const, the following occurs:
- Unexpected Allocations: Resources that should have been transferred (like heap-allocated buffers in a
std::vector or std::string) are instead deep-copied.
- Hidden Latency: Because the code compiles without warnings or errors, the transition from an $O(1)$ move to an $O(n)$ copy can introduce bottlenecks that are difficult to trace without profiling.
- False Assumptions: Developers may assume a resource is being released from the source object, while in reality, the source remains fully populated.
Verification Method
To verify this behavior in your specific environment (C++11 or later), you can use a simple diagnostic class:
#include <iostream>
#include <utility>
struct Tracker {
Tracker() = default;
Tracker(const Tracker&) { std::cout << "Copying...\n"; }
Tracker(Tracker&&) { std::cout << "Moving...\n"; }
};
int main() {
const Tracker c_obj;
Tracker target = std::move(c_obj); // Triggers Copy
return 0;
}
Assumptions and Diagnostics
This explanation assumes the use of standard move constructors. If your class implements a custom const T&& constructor, that overload would take precedence, though such patterns are rare as they cannot modify the source.
Diagnostic Detail: To provide a more specific recommendation, please specify if you are using a custom smart pointer or a third-party container that might have non-standard constructor overloads.