Consider a simple Coordinate class:
#include <iostream>
class Coordinate {
private:
int m_x {};
int m_y {};
public:
Coordinate(int x, int y)
: m_x { x }
, m_y { y }
{
}
int x() const{
return m_x;
}
int y() const{
return m_y;
}
};
void print(const Coordinate& coordinate){
std::cout << '(' << coordinate.x()
<< ", " << coordinate.y() << ")\n";
}
int main(){
Coordinate spawnPoint { 3, 5 };
print(spawnPoint);
}
// Terminal output:
(3, 5)
This is perfectly valid.
But if spawnPoint is only created so it can be passed into print(). This is inefficient.
We can do better.
We can merge these 2 instruction by using a temporary class object.
Creating a temporary class object
A temporary object is an unnamed object created for immediate use.
#include <iostream>
class Coordinate {
private:
int m_x {};
int m_y {};
public:
Coordinate(int x, int y)
: m_x { x }
, m_y { y }
{
}
int x() const{
return m_x;
}
int y() const{
return m_y;
}
};
void print(const Coordinate& coordinate){
std::cout << '(' << coordinate.x()
<< ", " << coordinate.y() << ")\n";
}
int main(){
print(Coordinate { 2, 2 });
print(Coordinate { 11, 7 });
}
// Terminal output:
(2, 2)
(11, 7)
This line creates a temporary Coordinate:
print(Coordinate { 2, 2 });
There is no variable name.
The object is constructed, passed to print(), used by print(), and then destroyed at the end of the full expression. All in one line.
NOTE: To make it even more concise, since print() expects a Coordinate we can do:
*print( {2, 2} ); at the cost of readability.*
Also, print() is a const lvalue reference since it has the power to bind to rvalues which is what we’re doing. We’re creating temporary class objects.
Takeaway
A temporary class object is an unnamed object created for immediate use:
print(Coordinate { 2, 2 });
Use temporaries when an object is only needed for one expression. They make call sites cleaner by avoiding unnecessary instantiations.