c++ - 为什么单例使用指针而不使用引用?
问题描述
我想使用引用编写一个 Meyers Singleton 类,但它不起作用。即使打印表明构造函数只被调用一次,我似乎仍然在每次调用实例访问器方法时获得类的单独实例。但是,如果我使用指针编写它,它就可以正常工作。谁能解释为什么以及如何修复参考版本?谢谢!
有效的指针版本:
Xh
class X {
public:
static X *getX(void);
void ipp();
int geti();
private:
X();
int i;
};
X.cpp
#include "X.h"
X::X()
{
printf ("X constructor\n");
i = 0;
}
X *X::getX()
{
static X the_only_X;
return &the_only_X;
}
int X::geti()
{
return (i);
}
void X::ipp()
{
i++;
}
试试看.cpp
#include <stdio.h>
#include "X.h"
int main (int ac, char *av[])
{
printf ("main\n");
X *x1 = X::getX();
x1->ipp();
printf ("i= %d\n", x1->geti());
X *x2 = X::getX(); // same X instance?
x2->ipp();
printf ("i= %d\n", x1->geti());
x1->ipp();
printf ("i= %d\n", x1->geti());
x2->ipp();
printf ("i= %d\n", x1->geti());
return (0);
}
构建并运行,应该得到 i= 1, 2, 3, 4:
g++ -Wall X.cpp tryit.cpp && ./a.out
main
X constructor
i= 1
i= 2
i= 3
i= 4
不起作用的参考版本:
Xh:
class X {
public:
static X& getX(void);
void ipp();
int geti();
private:
X();
int i;
};
X.cpp:
#include "X.h"
X::X()
{
printf ("X constructor\n");
i = 0;
}
X& X::getX()
{
static X the_only_X;
return the_only_X;
}
int X::geti()
{
return (i);
}
void X::ipp()
{
i++;
}
tryit.cpp:
#include <stdio.h>
#include "X.h"
int main (int ac, char *av[])
{
printf ("main\n");
X x1 = X::getX();
x1.ipp();
printf ("i= %d\n", x1.geti());
X x2 = X::getX(); // same X instance?
x2.ipp();
printf ("i= %d\n", x1.geti());
x1.ipp();
printf ("i= %d\n", x1.geti());
x2.ipp();
printf ("i= %d\n", x1.geti());
return (0);
}
构建并运行,应该得到 i= 1, 2, 3, 4:
ecd-imac27$ g++ -Wall X.cpp tryit.cpp && ./a.out
main
X constructor
i= 1
i= 1
i= 2
i= 2
解决方案
X x1 = X::getX();
正在制作单例实例的副本。也是如此X x2 = X::getX();
。这意味着您实际上拥有三个. X
哎呀。怎么会这样?这应该是一吨!
如果一个单例类是可复制和/或可移动的,那么它真的不是一个单例。因此,通过从您的类中删除复制和移动操作(默认情况下由编译器提供)来强制执行:
class X {
public:
static X& getX(void);
void ipp();
int geti();
private:
X();
X(const X&) = delete; // Copy ctor
X(X&&) = delete; // Move ctor
X& operator=(const X&) = delete; // Copy assignment
X& operator=(X&&) = delete; // Move assignment
int i;
};
完成此操作后,您会发现X x1 = X::getX();
并X x2 = X::getX();
无法编译。好的!编译器阻止您创建更多X
实例。通过使用引用来解决这个问题:
X& x1 = X::getX();
X& x2 = X::getX();
一切正常:
main
X constructor
i= 1
i= 2
i= 3
i= 4
推荐阅读
- html - 将自定义 css 类添加到 wordpress 中的导航菜单项
- angular - 为什么 Chrome 调试器中没有导入的打字稿功能
- apache-spark - SPARK_WORKER_CORES 和 SPARK_EXECUTOR_CORES 之间的区别?
- python - 复制 Python 对象并以不同的名称保存
- android - ViewModel 创建 2 个实例而不是 1 个
- javascript - 在Javascript中按索引删除组合二维数组的值
- java - 哪个 jar 文件包含 websphere 中的 org.apache.jetspeed.portlet.PortletWindow?
- pycharm - .kv 文件问题与 pycharm
- ssas - DAX - 计算多对多映射?
- redis - Redis Streams 可以作为 Flink 的源吗