zeus_masta_funk
zeus_masta_funk

Reputation: 1498

Ranged base for loop over temporary reference C++11

I'm wondering if the following is valid:

#include <iostream>
#include <vector>

std::vector<int>& getVec()
{
    static std::vector<int> vec{1, 2, 3, 4, 5};
    return vec;
}

int main()
{
    for (const auto& i : getVec())
    {
        std::cout << "i = " << i << std::endl;
    }
    return 0;
}

Basically I'm unsure about the lifetime of the temporary from getVec(). I've looked at both this post and this one, but am in a bit of a different situation as my function returns a reference to static data. Specifically, I'm wondering if scenario violates the following exception in the stated rule:

  • A temporary bound to a reference parameter in a function call [...]

or if this is indeed safe code. I think it is safe, but just wanted to be sure.

Upvotes: 1

Views: 97

Answers (1)

Miles Budnek
Miles Budnek

Reputation: 30579

Yes, this is fully valid and well-defined.

The range-based for loop in your question is defined to be equivilent to the following, for imaginary variables range, begin, and end:

auto&& range = getVec();
auto begin = std::begin(range);
auto end = std::end(range);
for (; begin != end; ++begin)
{
    const auto& i = *begin;
    {
        std::cout << "i = " << i << std::endl;
    }
}

After reference collapsing rules are applied, the type of range becomes std::vector<int>&. That means no temporaries are ever created. The loop iterates over the static vector defined in getVec.

If getVec instead returned by value, the type of range would be std::vector<int>&&, and lifetime extension would be applied. That would extend the lifetime of the temporary object to that of the reference, and everything would still be totally valid.

Upvotes: 2

Related Questions