Best practice resolving dangling const ref

sp2danny :

The following short program

#include <vector>
#include <iostream>

std::vector<int> someNums()
{
    return {3, 5, 7, 11};
}

class Woop
{
public:
    Woop(const std::vector<int>& nums) : numbers(nums) {}
    void report()
    {
        for (int i : numbers)
            std::cout << i << ' ';
        std::cout << '\n';
    }
private:
    const std::vector<int>& numbers;
};

int main()
{
    Woop woop(someNums());
    woop.report();
}

have a dangling reference problem, that no compiler seems to warn about. The issue is that temporaries can be bound to const-refs, which you may then keep around. The question then is; Is there a 'best practices' method of avoiding getting into this problem? Preferably one that does not involve sacrificing const correctness, or always making copies of big objects.

user7860670 :

In situation when some method keeps a reference after returning it is a good idea to utilize std::reference_wrapper instead of normal reference:

#include <functional>

class Woop
{
public:
    using NumsRef = ::std::reference_wrapper<const std::vector<int>>;
    Woop(NumsRef nums) : numbers_ref{nums} {}
    void report()
    {
        for (int i : numbers_ref.get())
            std::cout << i << ' ';
        std::cout << '\n';
    }
private:
    NumsRef numbers_ref;
};
  1. it already comes with a set of overloads preventing binding of rvalues and unintended passing of temporaries, so there is no need to bother with an extra prohibited overload taking a rvalue Woop (std::vector<int> const &&) = delete; for your method:
Woop woop{someNums()}; // error
woop.report();
  1. it allows implicit binding of lvalues so it won't break existing valid invocations:
auto nums{someNums()};
Woop woop{nums}; // ok
woop.report();
  1. it allows explicit binding of lvalues which is a good practice to indicate that caller will keep the reference after returning:
auto nums{someNums()};
Woop woop{::std::ref(nums)}; // even better because explicit
woop.report();

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=367805&siteId=1