【发布时间】:2018-08-29 11:25:43
【问题描述】:
这是一个为什么这个代码不能工作的问题。我想知道如何修复命名空间 dj 中的代码,而不是演示程序中的代码。在进一步阅读之前,您可能需要运行该程序。
当我通过std::thread 传递rvalue std::string 时,字符串到达并行函数时为空。也许原始值已被 std::moved,但最终出现在错误的位置。但我认为问题可能出在函数timer 上。那里我认为字符串是通过引用捕获的,当右值消失时,引用无效。
// In the demo program, the string is the one element of `...args`.
template<typename F, typename... Args>
void timer(double seconds, F& f, Args&&... args) {
auto th = std::thread(
[&, seconds] { delayed(seconds, f, std::forward<Args>(args)...); });
th.detach();
}
我不知道如何为 lambda 捕获内容。 & 号让我害怕,但我无法解决它。我在使用 bind 或 function 代替 lambda 方面进行了各种尝试。没有喜悦。
...
演示程序... 主线程启动一个暂停给定秒数的线程。然后新线程打印一个字符串并发出哔哔声,直到主线程将原子布尔值设置为 true。要显示它不起作用,请将全局布尔值 demo_the_problem 设置为 true。字符串到达报警函数时为空。
#include <thread>
#include <chrono>
#include <iostream>
static bool demo_the_problem = false;
namespace dj {
inline void std_sleep(long double seconds) noexcept
{
using duration_t = std::chrono::duration<long long, std::nano>;
const auto duration = duration_t(static_cast<long long> (seconds * 1e9));
std::this_thread::sleep_for(duration);
}
// Runs a command f after delaying an amount of time
template<typename F, typename... Args>
auto delayed(double seconds, F& f, Args&&... args) {
std_sleep(seconds);
return f(std::forward<Args>(args)...);
}
// Runs a function after a given delay. Returns nothing.
template<typename F, typename... Args>
void timer(double seconds, F& f, Args&&... args) {
auto th = std::thread( // XXX This appears to be where I lose ring_tone. XXX
[&, seconds] { delayed(seconds, f, std::forward<Args>(args)...); });
th.detach();
}
}
using namespace dj;
int main() {
std::atomic<bool> off_button(false);
// Test dj::timer, which invokes a void function after a given
// period of time. In this case, the function is "alarm_clock".
auto alarm_clock = [&off_button](const std::string ring_tone) {
char bel = 7;
std::cout << ring_tone << '\n';
while (!off_button) {
std_sleep(0.5);
std::cout << bel;
}
off_button = false;
};
auto ring = std::string("BRINNNNGGG!");
if (demo_the_problem)
timer(4.0, alarm_clock, std::string("BRINNNNGGG!")); // Not OK - ring arrives as empty string
else {
timer(4.0, alarm_clock, ring); // Ring tone arrives intact.
}
// Mess around for a while
for (int i = 0; i < 12; ++i) {
if (i == 7) {
off_button = true; // Hit the button to turn off the alarm
}
std::cout << "TICK ";
std_sleep(0.5);
std::cout << "tock ";
std_sleep(0.5);
}
// and wait for the button to pop back up.
while(off_button) std::this_thread::yield();
std::cout << "Yawn." << std::endl;
return 0;
}
【问题讨论】:
-
你确定 temp
std::string作为右值传递吗?将 temp 提升为 lvalue 的讨厌的 MS“功能”可能会有所帮助。 -
@Slava - 我希望不要有任何依赖于 MS“功能”的东西,我尽可能关闭。
标签: c++ multithreading visual-c++ stl c++17