user2982762
user2982762

Reputation: 84

Error with returning reference to temporary object

I have a following template function in c++

template<class S, class T> const T& safe_retrieve
(vector<T> const& data, vector<S> const& keys, const S& key)
{
    assert(data.size() == keys.size());
    typename vector<S>::const_iterator it = binary_find(keys.begin(), keys.end(), key);
    assert(it != keys.end());
    size_t index = static_cast<size_t>(it - keys.begin());
    return data.at(index);
}

However, I'm getting an error:

 error: returning reference to temporary [-Werror=return-local-addr]

I understand the meaning of this error, but I don't see why the reference that I'm returning is temporary.

Upvotes: 1

Views: 714

Answers (2)

YSC
YSC

Reputation: 40070

Since data is a std::vector<T> const&, it could be a temporary:

safe_retrieve(std::vector<int>{10,20}, std::vector<int>{1,2}, 2);

With that use of safe_retrieve, a temporary would be returned.


Minimal example

Source:

#include <iostream>
#include <vector>

int const& get(std::vector<int> const& data)
{
    return data.at(0);
}

int main() {
    int const& data = get(std::vector<int>{42, 0});
    std::cout << data << std::endl;
}

Compilation:

$ g++ -std=c++11 -O2 -Wall -Werror main.cpp && ./a.out

Run:

$ ./a.out
0

It should be 42, hello UB ;)

Upvotes: 0

mindriot
mindriot

Reputation: 5668

Just to turn my comment into a proper answer:

Your code assumes that vector<T>::at() const always returns a const T&. However, that is not always the case: The template specialization for std::vector<bool> has a different type of reference (a proxy for the respective bit in the internal bit vector implementation in lieu of a normal reference, and a plain bool value in lieu of a const reference). In this case, at() returns a temporary, which you cannot pass on using a reference.

The solution is to declare your function as follows:

template <class S, class T>
typename std::vector<T>::const_reference  // sic!
safe_retrieve(std::vector<T> const& data,
              std::vector<S> const& keys,
              const S& key)
{ ... }

Upvotes: 5

Related Questions