C++: Faster to Retrieve Data By Ref Parameter or Returning a Ref?

In C++, there are two options to retrieve data from a object: either passing a reference parameter to be filled up or returning a reference. The former is making a copy of data (which may be what the developer wants) while the latter is returning a memory address of the data.

The example code is hosted at Github.

void PassByReference(std::vector<int>& vec)
{
    vec = m_vec; // make a copy
}

std::vector<int>& ReturnReference()
{
    return m_vec; // return memory address
}

Since reference in C++ is a syntactic sugar for pointer, the pointer equivalent of the 2 above functions are presented below. By right, they should have the same performance characteristic.

void PassByPointer(std::vector<int>* vec)
{
    *vec = m_vec; // make a copy
}

std::vector<int>* ReturnPointer()
{
    return &m_vec; // return memory address
}

Benchmark Code

The code used for benchmark is below.

const int MAX_LOOP = 100000;
timer stopwatch;

{
    stopwatch.start("PassByReference");
    Foo foo;
    std::vector<int> vec;
    for (int i = 0; i < MAX_LOOP; ++i)
    {
        foo.Add(i);
        foo.PassByReference(vec);
    }
    stopwatch.stop();
}
{
    stopwatch.start("ReturnReference");
    Foo foo;
    std::vector<int>* p = nullptr;
    for (int i = 0; i < MAX_LOOP; ++i)
    {
        foo.Add(i);
        p = &foo.ReturnReference();
    }
    stopwatch.stop();
}
{
    stopwatch.start("PassByPointer");
    Foo foo;
    std::vector<int> vec;
    for (int i = 0; i < MAX_LOOP; ++i)
    {
        foo.Add(i);
        foo.PassByPointer(&vec);
    }
    stopwatch.stop();
}
{
    stopwatch.start("ReturnPointer");
    Foo foo;
    std::vector<int>* p = nullptr;
    for (int i = 0; i < MAX_LOOP; ++i)
    {
        foo.Add(i);
        p = foo.ReturnPointer();
    }
    stopwatch.stop();
}

Benchmark Results

The benchmark result for different C++ compilers are presented below.

Visual C++ 2019 16.7 Update on Windows 10 20.04 Update

     PassByReference timing:  565ms
     ReturnReference timing:    0ms
       PassByPointer timing:  572ms
       ReturnPointer timing:    0ms

G++ 9.3.0 Ubuntu 20.04 WSL2

G++ build command is as follows.

g++ -std=c++11 -O3 TestReference.cpp
     PassByReference timing: 8945ms
     ReturnReference timing:    0ms
       PassByPointer timing:  598ms
       ReturnPointer timing:    1ms

Clang++ 10.0.0 Ubuntu 20.04 WSL2

Clang++ build command is as follows.

clang++ -std=c++11 -O3 TestReference.cpp
     PassByReference timing: 8824ms
     ReturnReference timing:    0ms
       PassByPointer timing:  617ms
       ReturnPointer timing:    0ms

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

%d bloggers like this:
search previous next tag category expand menu location phone mail time cart zoom edit close