передача std :: thread по ссылке вызывает конструктор копирования

Ну, у меня есть проблема с передачей данных в поток, используя std :: thread. Я думал, что понял общую семантику конструкторов копирования и т. Д., Но, похоже, я не совсем понял проблему. У меня есть простой класс с именем 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<std::ostream *> 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;
}

Вы можете видеть, что main вызывает сервер функций и передает 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");
}

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

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

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

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

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

1> \ log.h (28): см. Объявление ‘Log’

: смотрите ссылку на создание шаблона функции ‘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 = Журнал &

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?

28

Решение

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

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

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

56

Другие решения

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

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

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

4

По вопросам рекламы ammmcru@yandex.ru
Adblock
detector