C++14遇到奇怪的 "use of deleted function"错误

标签 c++ reference c++14 auto

我在下面有一个简单的 g++7.3.1 -std=c++14 代码片段

#include<functional>
#include<iostream>
using namespace std;
struct S{
    int m_i = 2;
    auto& get2(){return ref(m_i);}
};
int main(){
    S s;
    s.get2()=4;
    cout<<s.m_i<<endl;
    return 0;
}

编译错误如下:

error: cannot bind non-const lvalue reference of type ‘std::reference_wrapper<int>&’ to an rvalue of type ‘std::reference_wrapper<int>’
    auto& get2(){return ref(m_i);}
                        ~~~^~~~~
In function ‘int main()’:
error: use of deleted function ‘std::reference_wrapper<_Tp>::reference_wrapper(_Tp&&) [with _Tp = int]’
    s.get2()=4;
            ^
In file included from /usr/include/c++/7/bits/std_function.h:44:0,
                from /usr/include/c++/7/functional:58,
                from xxx.cpp:1:
/usr/include/c++/7/bits/refwrap.h:338:7: note: declared here
    reference_wrapper(_Tp&&) = delete;
    ^~~~~~~~~~~~~~~~~

我知道,通过删除“ref”包装器,程序可以编译。我只想知道在这里使用“ref”有什么问题?

  1. 只要我希望返回一个引用,为什么在这里添加“ref”会导致错误?
  2. 我不明白为什么 g++ 将其视为“使用已删除的函数”,哪个函数被删除了?

最佳答案

您共享的代码存在许多问题。

第一个问题是您要返回对一个对象的引用,该对象在您的函数返回时将不再存在。 std::ref返回 std::reference_wrapper这将超出范围。一个std::reference_wrapper是一个对象,它提供了引用类型的一些功能,同时仍然表现得像一个对象。它具有移动语义,因此正确的用法是返回 std::reference_wrapper按值(value)。

#include<functional>
struct S {
    int m_i = 2;
    auto get2() { return std::ref(m_i); }
};

虽然正如其他人指出的那样,std::ref这里真的不需要。您可以只返回对 m_i 的引用直接地。如果用户恰好需要 std::reference_wrapper为此int , 他们可以调用 std::ref自己引用m_i你提供。

struct S {
    int m_i = 2;
    int & get2() { return  m_i; }
};

但这不是您的代码的唯一问题。假设您解决了第一个问题并返回您的 std::reference_wrapper按值(value)计算,您仍在滥用 std::reference_wrapper::operator= .该运算符不会为引用的对象分配新值。相反,它重新绑定(bind)引用以引用不同的实例。正确的用法是使用 get()获得适当的分配 int&来自 std::reference_wrapper :

#include<functional>
#include<iostream>
struct S {
    int m_i = 2;
    auto get2() { return std::ref(m_i); }
};

int main() {
    S s;
    s.get2().get() = 4;
    std::cout << s.m_i << std::endl;
    return 0;
}

但是错误信息呢?编译器看到唯一的 operator= std::reference_wrapper 存在是一个需要另一个std::reference_wrapper .所以它试图隐式转换 4std::reference_wrapper唯一的方法是尝试使用采用单个参数的构造函数。但是,不可能创建 std::reference_wrapper4 这样的文字(或一般的右值)。它需要一个合适的左值来引用。这可以通过声明一个构造函数来防止,该构造函数接受对包装类型的右值引用(在本例中为 int )并将其删除。尝试使用该构造函数将产生您所看到的错误。删除的函数是std::reference_wrapper<int>::reference_wrapper<int>(int&&) ,由编译器引入的转换调用。

关于C++14遇到奇怪的 "use of deleted function"错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52318618/

相关文章:

c++ - 我需要使用什么 Qt 类型来将 lambda 作为函数参数传递?

excel - 如何在vba引用库中查找函数

c++ - C++14 中的模板到模板映射

c++ - 通用 lambda : syntactic sugar or not?

c++ - 多个包含错误

c++ - 使用 Rcpp::IntegerVectors 添加 int

c++ - ffmpeg sws_scale 得到了从 YUV420P 到 RGB24 的失真图像

c++ - 改变这个指针指向的值

Java 递归,用对象调用它 - 如何复制对象?

c++ - 使用 std::unique_ptr 使用 CRTP 进行向上转换