我正在阅读cppreference 的 std::thread 文档(我知道,并不总是 100% 准确),并注意到以下关于std::thread
传递“指向数据成员的指针”(而不是“指向数据的指针”的行为的定义) member-function") 作为它的第一个参数 ( f
) 和所需类的对象作为它的第二个参数(t1
在复制到 thread-local-storage 之后):
如果 N == 1 并且 f 是指向类的成员数据对象的指针,则访问它。对象的值被忽略。有效地执行以下代码: t1.*f 如果 t1 的类型是 T,则引用 T 或引用派生自 T. (*t1).*f 的类型,否则。
现在,我不打算std::thread
以这种方式使用,但我对这个定义感到困惑。显然,唯一发生的事情是访问了数据成员并且忽略了该值,这似乎根本不会有任何可观察到的副作用,这意味着(据我所知)它也可能是一个无操作。(我可能遗漏了一些明显的东西......?)
起初,我认为这可能是印刷错误,意思是访问数据成员然后调用(因为它可能是可调用对象,即使它不是函数)但我在 GCC 中使用以下代码对其进行了测试-4.7 并且确实没有调用:
#include <iostream>
#include <thread>
struct S
{
void f() {
std::cout << "Calling f()" << std::endl;
}
struct {
void operator()() {
std::cout << "Calling g()" << std::endl;
}
} g;
};
int main(int, char**)
{
S s;
s.f(); // prints "Calling f()"
s.g(); // prints "Calling g()"
std::cout << "----" << std::endl;
auto x = &S::f; // ptr-to-mem-func
auto y = &S::g; // ptr-to-data-mem
(s.*x)(); // prints "Calling f()"
(s.*y)(); // prints "Calling g()"
std::cout << "----" << std::endl;
std::thread t(x, &s);
t.join();
// "Calling f()" printed by now
std::thread u(y, &s);
u.join();
// "Calling g()" not printed
return 0;
}
这个定义是否有任何目的似乎没有完成任何事情?为什么不让传递“指向数据成员可调用的指针”就像传递“指向成员函数的指针”一样,而让传递“指向数据成员不可调用的指针”成为错误?事实上,这似乎是实现它的最简单方法,因为调用“pointer-to-data-member-callable”与在其他上下文中调用“pointer-to-member-function”具有等效的语法(除非模板专业化和 SFINAE 规则的杂乱无章使得难以同等对待它们......?)
这不是我实际代码所需要的东西,但是这个定义存在的事实让我怀疑我错过了一些基本的东西,这让我很担心......有人能告诉我这个吗?