usar thread libreria ejemplos ejemplo c++ multithreading c++11 copy-constructor stdthread

libreria - thread c++ ejemplos



std:: paso de hilo por referencia llamadas copia constructor (2)

Obtengo un error de compilación cuando intento pasar el registrador (o el socket) al hilo por referencia

No es suficiente que la función de punto de entrada del hilo tome un tipo de referencia: el objeto de hilo toma sus argumentos por valor. Esto se debe a que generalmente quiere una copia de los objetos en un hilo separado.

Para evitar esto, puede pasar std::ref(logger) , que es una envoltura de referencia que oculta la semántica de referencia debajo de un objeto que se puede copiar.

Bueno, tengo un problema con pasar datos a un hilo usando std :: thread. Pensé que entendía la semántica general de los constructores de copias, etc. pero parece que no entiendo el problema. Tengo una clase simple llamada Log que ha ocultado su constructor de copia así:

class Log { public: Log(const char filename[], const bool outputToConsole = false); virtual ~Log(void); //modify behavior void appendStream(std::ostream *); //commit a new message void commitStatus(const std::string str); private: //members std::ofstream fileStream; std::list<std::ostream *> listOfStreams; //disable copy constructor and assignment operator Log(const Log &); Log & operator=(const Log &); }

ahora tengo una principal basada en gran medida en http://www.boost.org/doc/libs/1_55_0/doc/html/boost_asio/example/cpp11/echo/blocking_tcp_echo_server.cpp

int main() { static int portNumber = 10000; Log logger("ServerLog.txt", true); logger.commitStatus("Log Test String"); try { boost::asio::io_service ioService; server(ioService, portNumber, logger); } catch (std::exception &e) { std::cerr << "Exception " << e.what() << std::endl; logger.commitStatus(e.what()); } return 0; }

Puede ver que main llama al servidor de funciones y pasa el IOService, portNumber y logger. El registrador se pasa por referencia, así:

using boost::asio::ip::tcp; void server(boost::asio::io_service &ioService, unsigned int port, Log &logger) { logger.commitStatus("Server Start"); tcp::acceptor acc(ioService, tcp::endpoint(tcp::v4(), port)); while(true) { tcp::socket sock(ioService); acc.accept(sock); std::thread newThread(session, &sock, logger); newThread.detach(); } logger.commitStatus("Server closed"); }

Obtengo un error de compilación cuando intento pasar el registrador (o el socket) al hilo por referencia, pero no obtengo el error al pasarlo a la sesión () por referencia

static void session(tcp::socket *sock, Log &logger) { std::cout << " session () " << std::endl; }

Ahora pensé que entendía correctamente que una referencia es lo mismo que pasar un puntero. Es decir, no llama al constructor de copia, simplemente pasa el puntero, que le permite tratar sintácticamente como si no fuera un puntero.

error C2248: ''Log :: Log'': no ​​se puede acceder al miembro privado declarado en la clase ''Log''

1> / log.h (55): ver la declaración de ''Log :: Log''

1> / log.h (28): ver la declaración de ''Log''

...

: ver compilación de la referencia a la instanciación de la plantilla de función ''std :: thread :: thread (_Fn, _V0_t &&, _ V1_t)''

1> con

1> [

1> Fn = void ( _cdecl *) (boost :: asio :: ip :: tcp :: socket *, Log &),

1> _V0_t = boost :: asio :: ip :: tcp :: socket *,

1> _V1_t = Log &

1>]

Sin embargo, si lo modifico para pasar un puntero, todo es feliz

... std::thread newThread(session, &sock, &logger); ... static void session(tcp::socket *sock, Log *logger) { std::cout << " session () " << std::endl; }

¿Por qué está pasando por referencia llamando a mi copia constructor . ¿Hay algo especial aquí debido a std :: thread? ¿Entendí mal el constructor de copias y pasé por referencia?

Me sale un error diferente pero igualmente desconcertante si trato de usar std :: move () como se hace en el ejemplo. ¿Es posible que mi VS2012 no esté implementando C ++ 11 correctamente?


std::thread toma sus argumentos por valor. Puede recuperar la semántica de referencia utilizando std::reference_wrapper :

std::thread newThread(session, &sock, std::ref(logger));

Obviamente, debes asegurarte de que el logger sobrevive al hilo.