通过引用传递给接受通用引用的函数
Pass by reference to a function accepting a universal reference
我正在尝试使用 API 来设置基于 HTTP 调用的变量值。我可以在其中设置将在 HTTP 调用时设置的变量的函数是 T&& 类型。我想在不同的线程上访问这个变量。我试图简化问题并在以下代码中将其表示为两个线程,以相同的方式访问变量。
#include <iostream>
#include <thread>
#include <chrono>
class Values
{
public:
int i;
std::string s;
};
template<typename T>
void WriteCycle(T&& i)
{
using namespace std::chrono_literals;
while (true)
{
i++;
std::cout << i << std::endl;
std::this_thread::sleep_for(500ms);
}
}
template<typename T>
void ReadCycle(T&& i)
{
using namespace std::chrono_literals;
while (true)
{
std::cout << i << std::endl;
std::this_thread::sleep_for(500ms);
}
}
int main() {
auto v = new Values();
std::thread t1(WriteCycle<int>, v->i);
std::thread t2(ReadCycle<int>, v->i);
t1.join();
t2.join();
}
目前读线程没有看到变量有任何变化。我阅读了完美的转发、移动语义学和转发引用,但我没有理解(我主要编写 dotnet,我的 C++ 知识是 C++11 之前的知识)。我尝试了 std::move、std::ref 和 std::forward 的所有组合,但我无法让读取线程看到写入线程的变化。有没有办法在不更改函数的 T&& 输入类型的情况下解决这个问题(因为这是我尝试使用的 API 的一部分)?如何以线程安全的方式解决这个问题?
这样的表示法:
template<typename T>
void WriteCycle(T&& i)
并不是真正意义上的右值引用,它是指通用引用,它可以是左值引用或右值引用,具体取决于您传递的数据类型。
在你的例子中,它只是一个左值引用,所以它与移动语义无关。问题是线程构造函数对引用不太友好,你可能只想使用 std::ref
来解决它:
auto myRef = std::ref(v->i);
std::thread t1(WriteCycle<&int>, myRef);
std::thread t2(ReadCycle<&int>, myRef);
然而它仍然不是完美的,因为你想在线程之间使用互斥锁或原子值进行同步
我正在尝试使用 API 来设置基于 HTTP 调用的变量值。我可以在其中设置将在 HTTP 调用时设置的变量的函数是 T&& 类型。我想在不同的线程上访问这个变量。我试图简化问题并在以下代码中将其表示为两个线程,以相同的方式访问变量。
#include <iostream>
#include <thread>
#include <chrono>
class Values
{
public:
int i;
std::string s;
};
template<typename T>
void WriteCycle(T&& i)
{
using namespace std::chrono_literals;
while (true)
{
i++;
std::cout << i << std::endl;
std::this_thread::sleep_for(500ms);
}
}
template<typename T>
void ReadCycle(T&& i)
{
using namespace std::chrono_literals;
while (true)
{
std::cout << i << std::endl;
std::this_thread::sleep_for(500ms);
}
}
int main() {
auto v = new Values();
std::thread t1(WriteCycle<int>, v->i);
std::thread t2(ReadCycle<int>, v->i);
t1.join();
t2.join();
}
目前读线程没有看到变量有任何变化。我阅读了完美的转发、移动语义学和转发引用,但我没有理解(我主要编写 dotnet,我的 C++ 知识是 C++11 之前的知识)。我尝试了 std::move、std::ref 和 std::forward 的所有组合,但我无法让读取线程看到写入线程的变化。有没有办法在不更改函数的 T&& 输入类型的情况下解决这个问题(因为这是我尝试使用的 API 的一部分)?如何以线程安全的方式解决这个问题?
这样的表示法:
template<typename T>
void WriteCycle(T&& i)
并不是真正意义上的右值引用,它是指通用引用,它可以是左值引用或右值引用,具体取决于您传递的数据类型。
在你的例子中,它只是一个左值引用,所以它与移动语义无关。问题是线程构造函数对引用不太友好,你可能只想使用 std::ref
来解决它:
auto myRef = std::ref(v->i);
std::thread t1(WriteCycle<&int>, myRef);
std::thread t2(ReadCycle<&int>, myRef);
然而它仍然不是完美的,因为你想在线程之间使用互斥锁或原子值进行同步