如何解决悬空的 const ref

sp2*_*nny 18 c++

以下短节目

#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();
}
Run Code Online (Sandbox Code Playgroud)

有一个悬空引用问题,似乎没有编译器警告过。问题是临时文件可以绑定到 const-refs,然后您可以保留它。那么问题是;有没有办法避免陷入这个问题?最好是不涉及牺牲常量正确性或总是制作大对象的副本。

Gem*_*lor 11

使您的类不那么容易受到攻击的一种方法是添加一个带有右引用的已删除构造函数。这将阻止您的类实例绑定到临时对象。

Woop(std::vector<int>&& nums)  =delete;
Run Code Online (Sandbox Code Playgroud)

这个删除的构造函数实际上会使 O/P 代码无法编译,这可能是您正在寻找的行为?


use*_*670 8

在某些方法在返回后保留引用的情况下,使用std::reference_wrapper而不是正常引用是个好主意:

#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;
};
Run Code Online (Sandbox Code Playgroud)
  1. 它已经带有一组重载,可防止绑定右值和意外传递临时值,因此无需Woop (std::vector<int> const &&) = delete;为您的方法使用右值而担心额外的禁止重载:
Woop woop{someNums()}; // error
woop.report();
Run Code Online (Sandbox Code Playgroud)
  1. 它允许左值的隐式绑定,因此它不会破坏现有的有效调用:
auto nums{someNums()};
Woop woop{nums}; // ok
woop.report();
Run Code Online (Sandbox Code Playgroud)
  1. 它允许显式绑定左值,这是一个很好的做法,表明调用者将在返回后保留引用:
auto nums{someNums()};
Woop woop{::std::ref(nums)}; // even better because explicit
woop.report();
Run Code Online (Sandbox Code Playgroud)