我有两个单身人士课程。
第一个是对第二个成员的引用。
#include <memory>
class B
{
friend class A;
public:
static B& getInstance()
{
static B instance;
return instance;
}
private:
B()
: b(new int(5))
, c(8)
{};
B(B const&);
void operator=(B const&);
private:
std::auto_ptr<int> b;
int c;
};
class A
{
public:
static A& getInstance()
{
static A instance;
return instance;
}
private:
A()
: b(B::getInstance().b.get())
, cRef(B::getInstance().c)
{
};
A(A const&);
void operator=(A const&);
private:
int* b;
int& cRef;
};
int main()
{
return 0;
}
这段代码安全吗?
答案 0 :(得分:2)
我想是的。这两个实例都是从程序生命周期的第一次访问开始。唯一可能变得棘手的是破坏:如果A的析构函数使用了B的引用/指针,但B已经被破坏了。幸运的是,3.6.3中的标准保证(引用2012年草案):
&#34;如果完成的构造函数或动态初始化 具有静态存储持续时间的对象在之前排序 另外,对第二个析构函数的完成进行了排序 在第一个析构函数启动之前。&#34;
(我强调。)换句话说,保证静态对象的逆向破坏顺序。由于您的施工顺序很好,破坏的顺序也是如此。 A的参考/指针B将在整个A实例销毁过程中有效。
答案 1 :(得分:0)
这里你对对象数据一无所知,所以这个代码在单线程环境中是正确的。在多线程中添加对getInstance()方法的锁定:
static A& getInstance() {
Lock lock;
static A instance;
return instance;
}
但要注意B :: b存储为A中的指针。如果将来你能够改变B :: b,比如重置它,指针可能会变得不正确。
如果您的编译器在静态局部变量初始化部分支持C ++ 11标准(如@Mikhail注意到的那样),您可以避免这些锁定。
(顺便说一句:这些课程的目的是什么?没有公开的方法。)