在 std::thread 参数处引用

Reference at std::thread parameters

提问人:Артём Гаркавый 提问时间:2/23/2021 最后编辑:463035818_is_not_an_aiАртём Гаркавый 更新时间:2/23/2021 访问量:543

问:

我有两个功能

void f(const int &x) {}
void g(int& x) {}

我能做到

int x = 0;
std::thread t1(f, x);

但是我不能创造,在这种情况下我需要制作而不仅仅是,为什么有必要呢?std::thread t2(g, x)std::ref(x)x

为什么可以在没有?t1std::cref

C++ 多线程 引用 stdthread 传递 const-reference

评论

0赞 Tanveer Badar 2/23/2021
您收到的错误消息到底是什么?
3赞 François Andrieux 2/23/2021
std::thread将参数复制到函数中。 将对象包装在授予引用语义的 a 中,因此副本引用原始对象。std::refstd::reference_wrapper
0赞 Артём Гаркавый 2/23/2021
好的,我明白了。但是为什么没有成功创建呢?t1std::cref
1赞 Martin York 2/23/2021
所有涉及的参数的类型信息在 C++ 中都很重要。请写出一个可编译的示例来显示问题。从这里无法分辨,因为我们不知道是什么或是什么!std::thread t1(f, x)fx
0赞 Артём Гаркавый 2/23/2021
完整的代码 ideone.com/KjOIKc。当我更改为任何类型时,它也可以工作。为什么它被编译并且不要求通过?intxstd::cref

答:

2赞 prog-fh 2/23/2021 #1

如果没有 ,您的函数将无法按预期工作。f()std::cref()

虽然无意改变后面的值,但这并不意味着这个引用后面的值不能在其他地方发生变异。f()x

在此示例中,没有原始副本的副本被放入线程堆栈中,并引用此副本;我们看到 和 .std::cref()intx11

另一方面,with ,仍然引用原文;我们看到 和 .std::cref()x12

/**
  g++ -std=c++17 -o prog_cpp prog_cpp.cpp \
      -pedantic -Wall -Wextra -Wconversion -Wno-sign-conversion \
      -g -O0 -UNDEBUG -fsanitize=address,undefined -pthread
**/

#include <iostream>
#include <thread>

using namespace std::chrono_literals;
void
f(const int &x)
{
  std::cout << "x=" << x << '\n';
  std::this_thread::sleep_for(1000ms);
  std::cout << "x=" << x << '\n';
}

int
main()
{
  int i=1;
  // std::thread th{f, i}; // copy to thread stack
  std::thread th{f, std::cref(i)}; // reference the original i
  std::this_thread::sleep_for(500ms);
  i+=1;
  th.join();
  return 0;
}

评论

0赞 Артём Гаркавый 2/23/2021
谢谢!可惜C++通过隐身会复制对象。顺便说一句,为什么当我将 std::cref 更改为 std::ref 时,此代码有效?行为应该是一样的吗?
1赞 prog-fh 2/23/2021
@АртёмГаркавый 是一个引用,因此提供可变的引用包装器不会造成伤害。另一方面,提供一个 const-reference 包装器,其中需要对可变对象的引用(在您的问题中)会让编译器抱怨。xconstg()
0赞 Kuba hasn't forgotten Monica 2/23/2021
@АртёмГаркавый 可惜隐身C++会复制对象 “隐身”和“对C++的基本语义理解不够”之间有一条细线。这些语义并不是不言自明的,尽管它们确实出现在语言的设计过程中,并且通常是一种特殊的方式,否则“简单”的东西就会被破坏或变得不那么明显。这就是C++经验的意义:这种理解是有效使用语言所固有的。对于相对新手来说,很多东西看起来都是隐秘的,无论编程语言如何。