以下是单例类的代码
class single{
private:
int i;
single(int x): i(x){
}
public:
static single& getInstance(){
static single s(10);
return s;
}
void incPrint(){
++i;
cout i " ";
}
};
现在,相同的代码为2个不同的代码提供了两种不同的结果
single d1 = single::getInstance();
d1.incPrint();
d1.incPrint();
single d2 = single::getInstance();
d2.incPrint();
d2.incPrint();
此代码生成输出:
11 12 11 12
而这段代码
single & d1 = single::getInstance();
d1.incPrint();
d1.incPrint();
single & d2 = single::getInstance();
d2.incPrint();
d2.incPrint();
生成结果
11 12 13 14
其中后者是所需的输出。由于设计问题或用户编码问题,这是异常吗?如何确保只获得第二个结果?
由于
答案 0 :(得分:9)
T x = foo()
制作副本。
或表现为“好像”它制作副本。
T& x = foo()
时,foo
返回T&
引用时,只会参考。
将复制构造函数和复制赋值运算符设为私有。这将阻止人们制作所有副本。将复制赋值运算符设为私有可防止自我复制。
不能从getInstance
返回指向单身的指针。这将是让人们不知道始终存在实例的保证的绝对方式。指针指示它可以是空指针。
然而,最好的选择是不使用单身,如果你可以避免它。单身人士有很多问题。这些问题包括生命周期管理,线程安全以及与检测内存泄漏的工具的交互。
干杯&第h。,
答案 1 :(得分:2)
删除复制构造函数(将其设为私有)。 这将阻止人们制作副本。
另一种方法是返回指向getInstance()的单例的指针。这将是让人们知道他们对单身人士的提及的一种肯定方式。
第三种选择是在共享数据周围有一个可复制的包装类。
这个包装器有一个指针或类似的单例,可以复制。答案 2 :(得分:2)
您正在正确地返回对单例变量的引用,但它是您将其分配给的问题。
此代码:
single d1 = single::getInstance();
表示:
创建类型为single
的新变量并复制返回的引用以对其进行初始化。因此,每次执行此操作时,都会创建一个新变量,而不是使用单例变量。
此代码:
single & d1 = single::getInstance();
表示:
为与返回的引用相同的变量创建新引用。因此,每次执行此操作时,您都会根据需要获得对单例变量的引用。
要阻止自己(和其他人)犯这个错误,你应该把你的构造函数设为私有。