Consider a custom class X
holding some resource (for simplicity represented here by an integer member variable) with move constructor (MC), move assignment operator (MAO), and a custom swap function:
class X {
int i_;
public:
X(int i) : i_(i) { }
X(X&& rhs) = default; // move constructor
X& operator=(X&& rhs) = default; // move assignment operator
// X& operator=(X rhs) { std::swap(i_, rhs.i_); return *this; } // unifying assign. op.
friend void swap(X& lhs, X& rhs) { std::swap(lhs.i_, rhs.i_); }
int i() const { return i_; }
};
In the following benchmark code:
int main() {
int i1, i2;
std::cin >> i1 >> i2;
X x1(i1), x2(i2);
std::cout << x1.i() << x2.i();
swap(x1, x2);
std::cout << x1.i() << x2.i();
std::swap(x1, x2);
std::cout << x1.i() << x2.i();
}
swap(x1, x2)
simply swaps 2 integers.std::swap(x1, x2)
calls 1x MC and 2x MAO.- If MAO is substituted by unifying assignment operator (UAO),
std::swap(x1, x2)
calls 3x MC and 2x UAO.
(Tested with gcc/libstdc++).
Seemingly, custom swap
is very valuable since it avoids many function calls. However, when I look at dissassemled output of this program: https://godbolt.org/g/RMfZgL, all the functionality of MC, MAO, UAO, swap
and std::swap
is inlined directly into main
(gcc/clang with -O2
flag). Moreover, no object of type X
is created in the program, it works only with integers at the machine code level.
Therefore, it seems to me that there is no reason to provide custom swap
function for a class like X
.
QUESTIONS:
- Is it good practice to assume that a compiler will optimize out calls of MC and MAO/UAO inside
std::swap
? Or, should I rather define customswap
for all custom classes? - For what kinds of classes is custom
swap
really beneficial?