問題描述
好吧,我在使用 std::thread 將數(shù)據傳遞到線程時遇到了問題.我以為我了解復制構造函數(shù)等的一般語義,但似乎我不太明白這個問題.我有一個名為 Log 的簡單類,它因此隱藏了它的復制構造函數(shù):
Well I have an issue with passing data into a thread using std::thread. I thought I understood the general semantics of copy constructors, etc. but it seems I don't quite grasp the problem. I have a simple class called Log that has hidden it's copy constructor thusly:
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 &);
}
現(xiàn)在我有一個主要基于 http://www.boost.org/doc/libs/1_55_0/doc/html/boost_asio/example/cpp11/echo/blocking_tcp_echo_server.cpp
now I have a main based heavily on 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調用了函數(shù)server,傳遞了IOService、portNumber和logger.記錄器是通過引用傳遞的,因此:
You can see that main calls the function server and passes the IOService, portNumber and logger. The logger is passed by reference, thusly:
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");
}
當我嘗試通過引用將記錄器(或套接字)傳遞給線程時出現(xiàn)編譯器錯誤,但通過引用將它傳遞給 session() 時我沒有收到錯誤
I get a compiler error when I try to pass the logger (or the socket) to the thread by reference, but I do not get the error when passing it to the session() by reference
static void session(tcp::socket *sock, Log &logger)
{
std::cout << " session () " << std::endl;
}
現(xiàn)在我認為我正確理解了引用與傳遞指針相同.也就是說,它不調用復制構造函數(shù),它只是傳遞指針,它讓您在語法上將其視為不是指針.
Now I thought that I understood correctly that a reference is the same as passing a pointer. That is, it does not call the copy constructor, it simply passes the pointer, which it lets you syntactically treat like it's not a pointer.
錯誤 C2248:'Log::Log':無法訪問類 'Log' 中聲明的私有成員
error C2248: 'Log::Log' : cannot access private member declared in class 'Log'
1> log.h(55) : 見 'Log::Log' 的聲明
1> log.h(55) : see declaration of 'Log::Log'
1> log.h(28) : 見 'Log' 的聲明
1> log.h(28) : see declaration of 'Log'
...
:參見正在編譯的函數(shù)模板實例化'std::thread::thread(_Fn,_V0_t &&,_V1_t)'的參考
: see reference to function template instantiation 'std::thread::thread(_Fn,_V0_t &&,_V1_t)' being compiled
1> 與
1> [
1> Fn=void (_cdecl *)(boost::asio::ip::tcp::socket *,Log &),
1> Fn=void (_cdecl *)(boost::asio::ip::tcp::socket *,Log &),
1> _V0_t=boost::asio::ip::tcp::socket *,
1> _V0_t=boost::asio::ip::tcp::socket *,
1> _V1_t=日志 &
1> _V1_t=Log &
1>]
但是如果我修改它來傳遞一個指針,一切都會很開心
However if I modify it to pass a pointer, everything is happy
...
std::thread newThread(session, &sock, &logger);
...
static void session(tcp::socket *sock, Log *logger)
{
std::cout << " session () " << std::endl;
}
為什么通過引用傳遞調用我的復制構造函數(shù).由于std::thread,這里有什么特別的事情發(fā)生嗎?我是否誤解了復制構造函數(shù)并通過引用傳遞?
Why is passing by reference calling my copy constructor. Is there something special happening here because of std::thread? Did I misunderstand the copy constructor and pass by reference?
如果我像示例中那樣嘗試使用 std::move() ,我會得到一個不同但同樣令人困惑的錯誤.我的 VS2012 是否可能沒有正確實現(xiàn) C++11?
I get a different but equally baffling error if I try to use std::move() as it is done in the example. Is it possible my VS2012 is not implementing C++11 correctly?
推薦答案
std::thread
按值接受其參數(shù).你可以通過使用 std::reference_wrapper
:
std::thread
takes its arguments by value. You can get reference semantics back by using std::reference_wrapper
:
std::thread newThread(session, &sock, std::ref(logger));
顯然,您必須確保 logger
比線程壽命更長.
Obviously you must make sure that logger
outlives the thread.
這篇關于std::thread 通過引用調用復制構造函數(shù)的文章就介紹到這了,希望我們推薦的答案對大家有所幫助,也希望大家多多支持html5模板網!