Sunday, 1 June 2014

The missing ampersand

The ampersand operator (&) is used to show that a parameter should be passed by reference. What difference does it make?

Some background:

#include <iostream>
#include <vector>
#include <algorithm>
#include <ctime>
using namespace std;

int main()
{
    struct datalist {
        int id;
        vector <pair<int, string>> data;
    };
    vector<datalist> datalists;

    // Preparation: fill up datalists with sample data
    for (int i = 0; i < 10; i++) {
        datalist d; d.id = i;
        for (int j = 0; j < 1440; j++) {
            pair<int, string> p;
            p.first = i + j;
            p.second = "somedata";
            d.data.push_back(p);
        }
        datalists.push_back(d);
    }
    cout << "Ready to start, "; system("pause");

    // Start timing here
    clock_t t = clock();
    for_each(begin(datalists), end(datalists), [](datalist d){
        cout << d.id << endl;
        for_each(begin(d.data), end(d.data), [](pair<int, string> &s){
            s.second.append("abc");
        });
    });
    t = clock() - t;
    cout << "Ticks: " << t << endl;

    system("pause");
    return 0;
}


What this does is simply to read from a vector of datalist and perform some operations. The preparation time is ignored. So, how long did the read and write take? On my system, it took about 400 ticks. Of course, this is a crude way of measuring, and it will be different depending on system load, but it will do for now.

Let's make a minor change. Modify this

for_each(begin(datalists), end(datalists), [](datalist d){

to this

for_each(begin(datalists), end(datalists), [](datalist &d){

This time around, the operation took a mere 20 ticks. What really happened here is that without the ampersand, a local copy of the datalist d is made before using it, which takes time. With an ampersand, the parameter is passed by reference, so the operation is performed directly on the original data, and thus there is no overhead associated with copying the parameter. The overhead will be negligible for simple parameters like int and string, but for large data structures it will be costly.

The key point? Be careful when passing parameters, and for large data structures (e.g. video bitmaps), it will be wise to pass by reference.

No comments:

Post a Comment