问题
Consider this program that essentially creates std::thread
that calls the function func()
with arg
as argument:
#include <thread>
#include <iostream>
struct foo {
foo() = default;
foo(const foo&) { std::cout << "copy ctor" << std::endl; }
foo(foo&&) noexcept { std::cout << "move ctor" << std::endl; }
};
void func(foo){}
int main() {
foo arg;
std::thread th(func, arg);
th.join();
}
My output is
copy ctor
move ctor
move ctor
As far as I understand arg
is copied internally in the thread object and then passed to func()
as an rvalue (moved). So, I expect one copy construction and one move construction.
Why is there a second move construction?
回答1:
You pass argument to func
by value which should constitute the second move. Apparently std::thread
stores it internally one more time before calling func
, which AFAIK is absolutely legal in terms of the Standard.
回答2:
So, I expect one copy construction and one move construction.
The standard doesn't actually say that. An implementation is allowed to do extra internal move constructions.
Doing so is potentially less efficient though. This was https://gcc.gnu.org/PR69724 and has been fixed for the upcoming GCC 10 release.
来源:https://stackoverflow.com/questions/59601840/why-arguments-moved-twice-when-constructing-stdthread