我在下面有一个简单的 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”有什么问题?
- 只要我希望返回一个引用,为什么在这里添加“ref”会导致错误?
- 我不明白为什么 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
.所以它试图隐式转换 4
到std::reference_wrapper
唯一的方法是尝试使用采用单个参数的构造函数。但是,不可能创建 std::reference_wrapper
像 4
这样的文字(或一般的右值)。它需要一个合适的左值来引用。这可以通过声明一个构造函数来防止,该构造函数接受对包装类型的右值引用(在本例中为 int
)并将其删除。尝试使用该构造函数将产生您所看到的错误。删除的函数是std::reference_wrapper<int>::reference_wrapper<int>(int&&)
,由编译器引入的转换调用。
关于C++14遇到奇怪的 "use of deleted function"错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52318618/