提问人:xaviersjs 提问时间:1/11/2014 更新时间:1/11/2014 访问量:19771
std::thread 通过引用传递调用复制构造函数
std::thread pass by reference calls copy constructor
问:
好吧,我在使用 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 &);
}
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;
}
现在我以为我理解正确了,引用与传递指针相同。也就是说,它不调用复制构造函数,它只是传递指针,它允许您在语法上将其视为它不是指针。
错误 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?
答:
std::thread
按值获取其参数。您可以使用以下方法获取引用语义:std::reference_wrapper
std::thread newThread(session, &sock, std::ref(logger));
显然,您必须确保它比线程更长久。logger
评论
当我尝试通过引用将记录器(或套接字)传递给线程时,我收到编译器错误
线程的入口点函数仅采用引用类型是不够的:线程对象本身按值获取其参数。这是因为您通常希望在单独的线程中复制对象。
为了解决这个问题,你可以传递 ,这是一个在可复制对象下隐藏引用语义的引用包装器。std::ref(logger)
评论
session