构造std :: thread对象的过程中的详细信息 [英] Details in the process of constructing a std::thread object

查看:88
本文介绍了构造std :: thread对象的过程中的详细信息的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我对构造std::thread对象的细节感兴趣(并感到困惑).根据 cppreference ,线程函数和所有参数都是值复制的到一些线程可访问的存储,然后调用.

I'm interested in (and confused about) the details of constructing a std::thread object. According to cppreference, both the thread function and all arguments are value-copied to some thread-accessible storage, and then invoke.

1)这个线程可访问的存储到底是什么?在语义上是否等同于某种线程本地存储,并且在返回线程函数后销毁了变量?

1) What exactly is this thread-accessible storage? Is it semantically equivalent to some kind of thread-local storage, and the variables are destructed after the thread function returned?

2)当传递给线程函数时,参数的值类别是什么?关于cppreference的描述建议将它们作为l值传递(无论如何,它们都被赋予名称).我在GCC和clang上进行的测试似乎表明了相反的含义,即r值.具体来说,以下代码无法编译:

2) What is the value-category of the arguments when passed to the thread function? The description on cppreference suggests that they are passed as l-values (they are given names anyway). My tests on GCC and clang seem to suggest the opposite, i.e., r-values. Specifically, the following code does not compile:

void f(int& a) {
  std::cout << ++a << '\n';
}

int main() {
    std::thread t(&f, 1);
    t.join();
    return 0;
}

如果将f更改为

void f(int&& a) {
  std::cout << ++a << '\n';
}

int main() {
    std::thread t(&f, 1);
    t.join();
    return 0;
}

那么,标准对此有何看法?

So, what does the standard say about this?

推荐答案

1)此线程可访问的存储"位文本未在标准中直接表示.该标准只是说,该函数是用decay_copy获得的参数调用的.

1) This "thread-accessible storage" bit of text is not represented directly in the standard. The standard simply says that the function is invoked with arguments obtained by decay_copy.

2)如果仔细研究decay_copy,您会发现它按值返回 (因为它的返回类型是std::decay).因此,函数f是使用rvalue参数(实际上是prvalue参数)调用的.

2) If you study decay_copy closely, you will find that it returns by value (because its return type is std::decay of something). So the function f is called with rvalue arguments (prvalue arguments, in fact).

如果要传递左值(引用),则可以使用std::refstd::cref来包装它们.

If you want to pass lvalues (references), you can use std::ref and std::cref to wrap them.

确切的引用,C ++ 11 30.3.1.2/4:

The exact quote, C++11 30.3.1.2/4:

效果:构造一个thread类型的对象.新的执行线程使用 INVOKE(DECAY_COPY ( std::forward<F>(f)), DECAY_COPY (std::forward<Args>(args))...) 的调用执行 正在构造线程中评估 DECAY_COPY .此调用的任何返回值是 忽略了. [注意:这意味着调用f的副本不会引发任何异常 将被抛出到构造线程中,而不是新线程中. -尾注]如果调用 INVOKE(DECAY_COPY ( std::forward<F>(f)), DECAY_COPY (std::forward<Args>(args))...) 终止 除非有未捕获的异常,否则应调用std::terminate.

Effects: Constructs an object of type thread. The new thread of execution executes INVOKE(DECAY_COPY ( std::forward<F>(f)), DECAY_COPY (std::forward<Args>(args))...) with the calls to DECAY_COPY being evaluated in the constructing thread. Any return value from this invocation is ignored. [ Note: This implies that any exceptions not thrown from the invocation of the copy of f will be thrown in the constructing thread, not the new thread. —end note ] If the invocation of INVOKE(DECAY_COPY ( std::forward<F>(f)), DECAY_COPY (std::forward<Args>(args))...) terminates with an uncaught exception, std::terminate shall be called.

DECAY_COPY 在30.2.6/1中定义:

DECAY_COPY is defined in 30.2.6/1:

在本条款的某些地方,使用了 DECAY_COPY(x) 操作.所有这些用途均意味着调用函数 decay_copy(x)并使用结果,其中decay_copy的定义如下:

In several places in this Clause the operation DECAY_COPY(x) is used. All such uses mean call the function decay_copy(x) and use the result, where decay_copy is defined as follows:

template <class T> typename decay<T>::type decay_copy(T&& v)
{ return std::forward<T>(v); }

INVOKE 是在20.8.2中定义的,与cppreference描述您提供的链接中的调用的方式几乎相同.

INVOKE is defined in 20.8.2 pretty much in the same way as cppreference describes the invocation in the link you've provided.

这篇关于构造std :: thread对象的过程中的详细信息的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆