【问题标题】:Why am I using the deleted function 'void std::ref(const _Tp&&) [with _Tp = int]'为什么我使用已删除的函数 'void std::ref(const _Tp&&) [with _Tp = int]'
【发布时间】:2017-07-15 04:18:53
【问题描述】:
#include<iostream>
#include<utility>
#include<tuple>
#include<functional>
using namespace std;
int main()
{
    int i = 0;
    auto p = make_pair(ref(i), ref(i++));
    p.first++;
    p.second++;
    cout << "i = " << i << endl;
}

例如如果我像这样使用ref(),编译器会说

使用已删除的函数'void std::ref(const _Tp&&) [with _Tp = int]'

但是,如果我的代码正在跟踪

#include<iostream>
#include<utility>
#include<tuple>
#include<functional>
using namespace std;
int main()
{
    int i = 0;
    auto p = make_pair(ref(i), ref(++i));
    p.first++;
    p.second++;
    cout << "i = " << i << endl;
}

我会成功得到输出i = 3,所以我不明白为什么我会得到如此不同的答案。

【问题讨论】:

  • ref(i++) - 临时引用,++i 返回对原始变量的引用
  • @BlackMoses:请在回答部分中回答。
  • 非常感谢,经过反思,我认为ref(i++)是对临时的引用是很合理的

标签: c++ c++11 move-constructor deleted-functions


【解决方案1】:

std::ref 接受一个变量并为您提供类似于对该变量的引用的东西。

i++ 不是变量;这是暂时的。那是因为后增量是如何工作的。原始值增加,但表达式的计算结果为 old 值,并且需要一个临时值来保存该旧值,以便您可以读取它。

std::ref 不允许你使用临时的,以避免像这样的错误。否则它将是一个悬空引用。

另一方面,++i 只是将原始变量返回给您,因此您可以很好地引用它。

但是,您不能像这样将i++i 放在一起;这两个表达式相对于彼此的顺序是不确定的(或某事)。不惜一切代价避免这种代码。

【讨论】:

  • 我查看了排序,在 C++14 中,由于未排序的参数副作用,它是 UB,但在 C++17 中,它将是不确定的排序,即 ref(i) 可能读为 @ 987654329@ 在++i 的副作用完成之前或之后,但它不是UB。后一个文本在 N4606 中。 Reference
  • 我不确定 这种特殊情况 是 UB,因为 i 的值没有用于引用它的子表达式中。然而,一般观点是正确的
  • 当你说vector myvec{1,2,3};时也会出现这个问题参考(myvec [0])。你会得到:错误:使用已删除的函数'void std::ref(const _Tp&&)
猜你喜欢
  • 2019-11-11
  • 1970-01-01
  • 1970-01-01
  • 2021-06-29
  • 1970-01-01
  • 2017-04-24
  • 2013-03-24
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多