简体   繁体   English

构造std :: thread对象的过程中的细节

[英]Details in the process of constructing a std::thread object

I'm interested in (and confused about) the details of constructing a std::thread object. 我对构造std::thread对象的细节很感兴趣(并且很困惑)。 According to cppreference , both the thread function and all arguments are value-copied to some thread-accessible storage, and then invoke. 根据cppreference ,线程函数和所有参数都被值复制到一些线程可访问的存储,然后调用。

1) What exactly is this thread-accessible storage? 1)这个线程可访问的存储到底是什么? Is it semantically equivalent to some kind of thread-local storage, and the variables are destructed after the thread function returned? 它在语义上等同于某种线程局部存储,并且在返回线程函数后变量被破坏了吗?

2) What is the value-category of the arguments when passed to the thread function? 2)传递给线程函数时参数的值类别是什么? The description on cppreference suggests that they are passed as l-values (they are given names anyway). 关于cppreference的描述表明它们作为l值传递(无论如何它们都被赋予了名称)。 My tests on GCC and clang seem to suggest the opposite, ie, r-values. 我对GCC和clang的测试似乎暗示了相反的,即r值。 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;
}

It compiles if we change f to 如果我们将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) This "thread-accessible storage" bit of text is not represented directly in the standard. 1)该文本的“线程可访问存储”位不直接在标准中表示。 The standard simply says that the function is invoked with arguments obtained by decay_copy . 该标准简单地说,使用decay_copy获得的参数调用该函数。

2) If you study decay_copy closely, you will find that it returns by value (because its return type is std::decay of something). 2)如果你仔细研究decay_copy ,你会发现它按值返回(因为它的返回类型是std::decay of something)。 So the function f is called with rvalue arguments (prvalue arguments, in fact). 所以函数f用rvalue参数调用(实际上是prvalue参数)。

If you want to pass lvalues (references), you can use std::ref and std::cref to wrap them. 如果要传递lvalues(引用),可以使用std::refstd::cref来包装它们。

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

Effects: Constructs an object of type thread . 效果:构造一个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. 新的执行线程执行INVOKE(DECAY_COPY ( std::forward<F>(f)), DECAY_COPY (std::forward<Args>(args))...) ,在构造线程中对DECAY_COPY的调用进行评估。 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. [ 注意:这意味着从f的副本的调用中抛出的任何异常都将在构造线程中抛出,而不是新线程。 —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. -end note ]如果调用INVOKE(DECAY_COPY ( std::forward<F>(f)), DECAY_COPY (std::forward<Args>(args))...)以未捕获的异常终止, std::terminate应被称为。

DECAY_COPY is defined in 30.2.6/1: DECAY_COPY在30.2.6 / 1中定义:

In several places in this Clause the operation DECAY_COPY(x) is used. 在本条款的几个地方使用了DECAY_COPY(x)操作。 All such uses mean call the function decay_copy(x) and use the result, where decay_copy is defined as follows: 所有这些用法意味着调用函数decay_copy(x)并使用结果,其中decay_copy定义如下:

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

INVOKE is defined in 20.8.2 pretty much in the same way as cppreference describes the invocation in the link you've provided. INVOKE在20.8.2中的定义与cppreference描述您提供的链接中的调用的方式非常相似。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM