你可以做一個包裝類,延遲對象的構造。然後,當它的第一次使用時,如果構造函數拋出,它將拋出第一次使用它的地方。
這樣做的好處是在調用main()之前不會有大量代碼運行,並且如果您沒有實際使用全局對象,它將永遠不會被初始化。
代碼:
#include <boost/bind.hpp>
#include <boost/function.hpp>
#include <boost/scoped_ptr.hpp>
#include <boost/thread/once.hpp>
#include <iostream>
const boost::once_flag DEFAULT_ONCE_FLAG = BOOST_ONCE_INIT;
template <typename T>
class DelayedConstruction {
public:
DelayedConstruction(boost::function<T* (void) > const & init = &DelayedConstruction::default_initializer) :
m_initializer(init), m_flag(DEFAULT_ONCE_FLAG) { }
T const & operator*() const {
boost::call_once(m_flag, boost::bind(&DelayedConstruction::initialize, this)) ;
if (! m_object)
throw std::runtime_error("Object could not be initialized") ;
return *m_object ;
}
T const * operator->() const {
boost::call_once(m_flag, boost::bind(&DelayedConstruction::initialize, this)) ;
if (! m_object)
throw std::runtime_error("Object could not be initialized") ;
return m_object.get() ;
}
static T* default_initializer() { return new T; }
private:
void initialize() const {
m_object.reset(m_initializer()) ;
}
boost::function<T* (void) > m_initializer ;
mutable boost::scoped_ptr<T> m_object ;
mutable boost::once_flag m_flag ;
};
struct Foo {
Foo(int x = 0) : m_x(x) {
if (x == 1) throw std::runtime_error("Can't be 1") ;
}
int m_x ;
} ;
Foo* make_custom_foo() {
return new Foo(1) ;
}
DelayedConstruction< const Foo > g_myFoo ;
DelayedConstruction< const Foo > g_anotherFoo(&::make_custom_foo) ;
int main() {
try {
std::cout << "My Foo: " << g_myFoo->m_x << std::endl ;
std::cout << "Another Foo: " << g_anotherFoo->m_x << std::endl ;
} catch (std::runtime_error const & e) {
std::cout << "ERROR: " << e.what() << std::endl ;
}
return 0 ;
}
打印出:
My Foo: 0
ERROR: Can't be 1
來源
2010-02-25 01:16:38
Eld
只是引起它的const並不意味着你不關心它被多次初始化。它可以訪問一個你真正只想要擊中一次的資源。 SomeOtherFunction也可能需要很長時間才能運行。無論如何,在main運行之前,你可能不希望它執行。 – Eld 2010-02-26 05:12:03
的確,我只是想指出可能不需要擔心同步:'const'意味着它在初始化後永遠不會改變,而如果不是(例如想到一個計數器),那麼在重新設置之後被使用會把事情搞砸。當然,這取決於OP來減輕手頭上的風險......我將編輯答案,以使最後一點更加清晰。 – 2010-02-26 07:16:05
我很確定我的代碼沒有任何線程問題,它應該在任何額外線程啓動之前進行初始化。我已經實施了這個解決方案,它似乎解決了這個問題。謝謝! – rmeador 2010-02-26 15:54:13