std :: thread pass by reference calls copy constructor

Ну, у меня есть проблема с передачей данных в stream с использованием std :: thread. Я думал, что понял общую семантику конструкторов копирования и т. Д., Но, похоже, я не совсем понимаю проблему. У меня есть простой class Log, который скрыл его конструктор копирования:

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 listOfStreams; //disable copy constructor and assignment operator Log(const Log &); Log & operator=(const Log &); } 

теперь у меня есть основная основа, основанная на 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; } 

Вы можете видеть, что основной вызов вызывает функциональный сервер и передает IOService, portNumber и logger. Регистратор передается по ссылке:

 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"); } в 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"); } 

Я получаю ошибку компилятора, когда пытаюсь передать регистратор (или сокет) в stream по ссылке, но я не получаю ошибку при передаче ее в сеанс () по ссылке

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

Теперь я подумал, что правильно понял, что ссылка такая же, как передача указателя. То есть, он не вызывает конструктор копирования, он просто передает указатель, который он позволяет синтаксически обрабатывать, как будто это не указатель.

ошибка C2248: ‘Log :: Log’: не может получить доступ к закрытому члену, объявленному в classе ‘Log’

1> \ log.h (55): см. Объявление «Log :: Log»

1> \ log.h (28): см. Объявление «Журнал»

: см. ссылку на экземпляр шаблона функции ‘std :: thread :: thread (_Fn, _V0_t &&, _ V1_t)’, скомпилированный

1> с

1> [

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

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

1> _V1_t = Log &

1>]

Однако, если я изменю его, чтобы передать указатель, все будет счастливо

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

Почему передача по ссылке вызывает мой конструктор копирования . Что-то особенное происходит здесь из-за std :: thread? Я неправильно понял конструктор копирования и передал ссылку?

Я получаю другую, но столь же непонятную ошибку, если я пытаюсь использовать std :: move (), как это сделано в примере. Возможно ли, что мой VS2012 не реализует C ++ 11 правильно?

    std::thread принимает свои аргументы по значению. Вы можете получить ссылочную семантику с помощью std::reference_wrapper :

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

    Очевидно, что вы должны убедиться, что logger переживает stream.

    Я получаю ошибку компилятора, когда пытаюсь передать регистратор (или сокет) в stream по ссылке

    Недостаточно, чтобы функция входной точки streamа принимала ссылочный тип: сам объект streamа принимает свои аргументы по значению. Это потому, что вы обычно хотите копию объектов в отдельном streamе.

    Чтобы обойти это, вы можете передать std::ref(logger) , который является ссылочной оболочкой, скрывающей ссылочную семантику под скопируемым объектом.

    Давайте будем гением компьютера.