我想创建一些Timer
类,每隔N秒打印一次“text”,其中N将在构造函数中初始化。
#include <boost/asio.hpp>
#include <boost/bind.hpp>
#include <boost/enable_shared_from_this.hpp>
#include <iostream>
class Timer : public boost::enable_shared_from_this<Timer>
{
public:
Timer ( const double interval ) : interval_sec( interval )
{
io_service_ = new boost::asio::io_service;
timer_ = new boost::asio::deadline_timer ( * io_service_ );
start( );
io_service_ -> run( );
}
void start ( )
{
timer_ -> expires_from_now( boost::posix_time::seconds( 0 ) );
timer_ -> async_wait(boost::bind( &Timer::handler
, shared_from_this( )
, boost::asio::placeholders::error
)
);
}
private:
void handler( const boost::system::error_code& error )
{
if ( error )
{
std::cerr << error.message( ) << std::endl;
return;
}
printf( "text\n" );
timer_ -> expires_from_now( boost::posix_time::seconds( interval_sec ) );
timer_ -> async_wait( boost::bind( &Timer::handler
, shared_from_this( )
, boost::asio::placeholders::error
)
);
}
private:
boost::asio::io_service * io_service_;
boost::asio::deadline_timer * timer_;
double interval_sec;
};
int main()
{
boost::shared_ptr<Timer> timer( new Timer ( 10 ) );
return 0;
}
但我有bad_weak_ptr
错误。
terminate called after throwing an instance of 'boost::exception_detail::clone_impl<boost::exception_detail::error_info_injector<boost::bad_weak_ptr> >'
what(): tr1::bad_weak_ptr
Aborted
我做错了什么,如何解决?
答案 0 :(得分:27)
问题很可能是在对象实际由共享指针管理之前不能使用shared_from_this
。通常,在构造函数中启动线程或异步服务并不是一个好主意,因为您可能不幸并且新线程可能在构造函数完成之前启动,因此在未完全构造的对象上执行。
在您的特定情况下,更糟糕的是,当您在Timer
类的构造函数中输入事件循环时,这意味着控件永远不会返回到main
,对象永远不会被管理在主要的shared_ptr
...
您应该将通话移至start
并将run()
的通话移至其他功能,并在实际管理对象后从main
调用该通话在shared_ptr
。
答案 1 :(得分:10)
在致电shared_from_this()
之前,您的课程需要存储在shared_ptr
中。这意味着你不能在构造函数中调用shared_from_this()
,因为直到构造函数完成之后,对象才会被放入shared_ptr中。
这就是使用enable_shared_from_this
的类通常具有start
函数的原因,该函数执行需要使用shared_from_this()
的初始化的最后步骤。在完全构造对象之后需要调用该start函数,因此不能像你一样从构造函数内部调用它。