The usual meaning of unary operators such as bitwise inversion, postfix increment, and unary minus is to return a modified copy of their argument. When their argument is a temporary, is there a way to modify that original object, thus avoiding the creation and destruction of a second object?
The examples below both involve two objects:
#include <utility>
#include <iostream>
using namespace std;
struct X {
~X() { cout << "destroy\n"; }
X() { cout << "default construct\n"; }
X(const X& ) { cout << "copy construct\n"; }
X( X&&) { cout << "move construct\n"; }
X& operator=(const X& ) { cout << "copy assign\n"; return *this; }
X& operator=( X&&) { cout << "move assign\n"; return *this; }
X operator~() const & { cout << "~lvalue\n"; return *this; }
X operator~() && { cout << "~rvalue\n"; return move(*this); }
};
int main(int, char**) {
{
cout << "Example 1\n";
auto a = X();
auto b = ~a;
}
{
cout << "Example 2\n";
auto a = ~X();
}
}
I get this output (ignore that ~lvalue and copy construct "appear" out of order):
Example 1
default construct
~lvalue
copy construct
destroy
destroy
Example 2
default construct
~rvalue
move construct
destroy
destroy
Is there a way to rewrite the struct so that example 2 only creates and destroys a single object?
Is there a way to rewrite the struct so that example 2 only creates and destroys a single object?
But your code says to create two objects. You create a prvalue and then perform an operation on it which is not initializing some other object. That operation requires manifesting a temporary from that prvalue. That's object 1.
Then you use auto a
to create a new object. That's object 2.
It doesn't matter what operator~
is doing; you must manifest a temporary from the prvalue, since operator~
needs to have a this
. Even if the return value is a &&
to this
(which is absolutely should not, because operator~
should be a const
function), that wouldn't help, because a
is a separate object. You can move construct a
, but it won't ever not be a separate object.
If you only want one object, you have to use code that says to create only one object: auto a = X(); a.invert();
.