Search code examples
c++11initializer-list

Function taking std::initializer_list


I came across a function a colleague had written that accepted an initializer list of std::vectors. I have simplified the code for demonstration:

int sum(const std::initializer_list<std::vector<int>> list)
{
    int tot = 0;
    for (auto &v : list)
    {
        tot += v.size();
    }
    return tot;
}

Such a function would allow you call the function like this with the curly braces for the initializer list:

std::vector<int> v1(50, 1);
std::vector<int> v2(75, 2);
int sum1 = sum({ v1, v2 });

That looks neat but doesn't this involve copying the vectors to create the initializer list? Wouldn't it be more efficient to have a function that takes a vector or vectors? That would involve less copying since you can move the vectors. Something like this:

int sum(const std::vector<std::vector<int>> &list)
{
    int tot = 0;
    for (auto &v : list)
    {
        tot += v.size();
    }
    return tot;
}

std::vector<std::vector<int>> vlist;
vlist.reserve(2);
vlist.push_back(std::move(v1));
vlist.push_back(std::move(v2));
int tot = sum2(vlist);

Passing by initializer list could be useful for scalar types like int and float, but I think it should be avoided for types like std::vector to avoid unnecessary copying. Best to use std::initializer_list for constructors as it intended?


Solution

  • That looks neat but doesn't this involve copying the vectors to create the initializer list?

    Yes, that is correct.

    Wouldn't it be more efficient to have a function that takes a vector or vectors?

    If you are willing to move the contents of v1 and v2 to a std::vector<std::vector<int>>, you could do the samething when using std::initializer_list too.

    std::vector<int> v1(50, 1);
    std::vector<int> v2(75, 2);
    int sum1 = sum({ std::move(v1), std::move(v2) });
    

    In other words, you can use either approach to get the same effect.