her*_*tao 4 c++ multithreading pointers this-pointer c++11
在书中的"C++ Concurrency in Action"§3.3.1中,在介绍使用类成员的线程安全延迟初始化时std::call_once(),它给出了以下示例:
#include <mutex>
struct connection_info
{};
struct data_packet
{};
struct connection_handle
{
void send_data(data_packet const&)
{}
data_packet receive_data()
{
return data_packet();
}
};
struct remote_connection_manager
{
connection_handle open(connection_info const&)
{
return connection_handle();
}
} connection_manager;
class X
{
private:
connection_info connection_details;
connection_handle connection;
std::once_flag connection_init_flag;
void open_connection()
{
connection=connection_manager.open(connection_details);
}
public:
X(connection_info const& connection_details_):
connection_details(connection_details_)
{}
void send_data(data_packet const& data)
{
std::call_once(connection_init_flag,&X::open_connection,this);
connection.send_data(data);
}
data_packet receive_data()
{
std::call_once(connection_init_flag,&X::open_connection,this);
return connection.receive_data();
}
};
int main()
{}
Run Code Online (Sandbox Code Playgroud)
从它的doc,第三个参数是传递给函数的参数X::open_connection().为什么this在调用std::call_once()给定X::open_connection()没有输入参数时需要指针?
std::call_once(connection_init_flag,&X::open_connection,this);
Run Code Online (Sandbox Code Playgroud)
PS:删除this指针将导致C2064错误:
error C2064: term does not evaluate to a function taking 0 arguments
更新:在引入类似函数时,在"C++并发操作"一书的§4.2.1中进一步明确了这个问题,即std::async:
如果第一个参数(应该是第二个参数
std::call_once)是指向成员函数的指针,则第二个参数(应该是第三个参数std::call_once)提供应用成员函数的对象(直接或通过指针,或包装std::ref),其余的参数作为参数传递给成员函数.否则,第二个(应该是第三个std::call_once)和后续参数作为参数传递给指定为第一个参数的函数或可调用对象.
jua*_*nza 12
调用std :: call_once()时为什么需要这个指针?
因为open_connection是非静态数据成员.必须在某些东西上调用它,并且某些东西是相同的实例,指向this(技术上,非静态成员函数具有隐含的第一个参数this.)
可以使用不同的实例调用它,尽管在这种情况下这没有意义:
X x;
std::call_once(connection_init_flag, &X::open_connection, &x);
Run Code Online (Sandbox Code Playgroud)
juanchopanza是正确的,我想补充一点,如果你用严格等效的lambda替换参数或你的代码片段,你实际上做的可能会更清楚:
std::call_once(connection_init_flag, [&]{ open_connection(); } );
// or
std::call_once(connection_init_flag, [this]{ open_connection(); } );
Run Code Online (Sandbox Code Playgroud)
这也完全等同于:
std::call_once(connection_init_flag, [this]{ this->open_connection(); } );
Run Code Online (Sandbox Code Playgroud)