#115 – Temporary class objects: construct, use, discard

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

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.