В книге «Параллельность C ++ в действии» §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()
{}
От его документ, третий параметр — это параметр, передаваемый в функцию X::open_connection()
, Почему this
указатель нужен здесь при звонке std::call_once()
При условии X::open_connection()
не имеет входного параметра?
std::call_once(connection_init_flag,&X::open_connection,this);
П.С .: Удаление this
указатель вызовет ошибку C2064:
error C2064: term does not evaluate to a function taking 0 arguments
Обновлено: Эта проблема более подробно рассматривается в п. 4.2.1 книги «Параллельность C ++ в действии» при введении аналогичных функций, т.е. std::async
:
Если первый аргумент (должен быть вторым для
std::call_once
) — указатель на функцию-член, второй аргумент (должен быть третьим дляstd::call_once
) предоставляет объект, к которому применяется функция-член (либо напрямую, либо через указатель, либо в видеstd::ref
), а остальные аргументы передаются в качестве аргументов функции-члену. В противном случае второй (должен быть третьим дляstd::call_once
) и последующие аргументы передаются в качестве аргументов функции или вызываемому объекту, указанному в качестве первого аргумента.
Зачем нужен этот указатель при вызове std :: call_once ()?
Так как open_connection
является нестатическим членом данных. Это должно быть вызвано чем-то, и что-то является тем же экземпляром, на который указывает this
(технически, нестатические функции-члены имеют неявный первый параметр для this
.)
Он мог быть вызван с другим экземпляром, хотя в этом случае это не имело бы смысла:
X x;
std::call_once(connection_init_flag, &X::open_connection, &x);
juanchopanza верен, я хотел бы добавить, что то, что вы на самом деле делаете, могло бы быть более понятным, если вы замените аргументы или ваш фрагмент кода на строго эквивалентную лямбду:
std::call_once(connection_init_flag, [&]{ open_connection(); } );
// or
std::call_once(connection_init_flag, [this]{ open_connection(); } );
Что также в точности эквивалентно:
std::call_once(connection_init_flag, [this]{ this->open_connection(); } );