skip to Main Content

In the following code:

#include <execution>
#include <vector>

template<typename T> 
class Index {
public:    
    const std::string& text;
    const std::vector<T>& index;

    decltype(index.begin())& begin() { return index.begin(); } // No warning
    decltype(index.end())&   end()   { return index.end(); }  // No warning

    const decltype(index.cbegin())& begin() const { return index.cbegin(); }
    const decltype(index.cend())&   end() const { return index.cend(); }
};

int main()
{
}

Visual Studio 2022 (recent version) gives warnings:

warning C4172: returning address of local variable or temporary

twice for every line with decltype. At the same time godbolt with the same configuration doesn’t.

Is this false-positive warnings or the code should be fixed?

My intention in the code to return const reference to const iterators. Is this correct approach/syntax for this?

Update

Interesting thing that for non-const version (just added to the source code above) none of compilers give a warning, although we still have the same reference to local copy.

Update 2

As a second thought, is there a way to return not iterators, but the begin/end functions themselves to make it even more transparent?

2

Answers


  1. You’re not returning the thing you have by reference, you’re returning the results of a function call.

    That the function happens to be on a method you have a reference to is irrelevant.

    const std::vector<T>& index;
    
    
    const decltype(index.cbegin())& begin() const { return index.cbegin(); }
    
    Login or Signup to reply.
  2. It’s not a false positive, and you can reproduce it on Compiler Explorer if you instantiate the class template:

    template class Index<int>;
    

    MSVC gives you the warning you’ve already posted, and GCC gives you

    <source>:10:72: warning: returning reference to temporary [-Wreturn-local-addr]
       10 |     const decltype(index.cbegin())& begin() const { return index.cbegin(); }
          |                                                            ~~~~~~~~~~~~^~
    

    The issue is that index.cbegin() returns an iterator by value, not by reference.
    The return type is const std::vector::const_iterator&, and this const& binds to a temporary const_iterator object.

    Note on performance considerations

    You’ve said that you’re returning the iterator by const& because

    performance consideration for the cases when iterator size is big enough to have impact.

    This is not something you should worry about.
    Iterators are a generalization of pointers ([iterator.requirements.general] p1) and are meant to be small, lightweight objects that can be passed around by value cheaply.
    If an iterator is expensive to pass around, that’s a design issue with the iterator.

    Note that standard library algorithms in <algorithm> also take iterators by value.

    Note on language evolution

    If P2748: Disallow Binding a Returned Glvalue to a Temporary is accepted into the C++26 standard (and the consensus is overall favorable), then your code will be ill-formed.

    In other words, it likely won’t even compile in C++26.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search