c++ - std::thread通过引用传递调用复制构造函数

标签 c++ multithreading c++11 copy-constructor stdthread

好吧,我在使用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");
}

当我尝试通过引用将记录器(或套接字)传递给线程时,出现编译器错误,但通过引用将记录器(或套接字)传递给session()时,我没有得到错误
static void session(tcp::socket *sock, Log &logger)
{
    std::cout << " session () " << std::endl;
}

现在,我认为我正确理解了引用与传递指针相同。也就是说,它不调用复制构造函数,它只是传递指针,它使您可以在语法上将其视为不是指针。

error C2248: 'Log::Log' : cannot access private member declared in class 'Log'

1> \log.h(55) : see declaration of 'Log::Log'

1> \log.h(28) : see declaration of 'Log'

...

: see reference to function template instantiation 'std::thread::thread(_Fn,_V0_t &&,_V1_t)' being compiled

1> with

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超过该线程的生命周期。

关于c++ - std::thread通过引用传递调用复制构造函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59101843/

相关文章:

c++ - thread_local 对象的销毁

c++ - 如何调用 DLL API

c++ - 在程序中实现线程的问题

c++ - window 打不开

c - posix 的线程优先级

multithreading - 如何使用 Arc 在线程之间共享可变对象?

.net - 用于在.NET/Windows窗体中执行长时间运行的操作的库?

c++ - 可 move 但不可复制的对象:按值传递还是按引用传递?

c++ - 为程序中所有可能路径的运行生成数据

c++ - 有没有办法检测混合类型和非类型的任意模板类?