为什么单身人士使用指针而不使用引用?
why is singleton working with pointers but not with references?
我想使用引用编写 Meyers Singleton class,但它不起作用。我似乎仍然在每次调用实例访问器方法时获得 class 的单独实例,即使打印表明构造函数只被调用一次。但是,如果我使用指针编写它,它就可以正常工作。谁能解释为什么以及如何修复参考版本?谢谢!
有效的指针版本:
X.h
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:
g++ -Wall X.cpp tryit.cpp && ./a.out
main
X constructor
i= 1
i= 2
i= 3
i= 4
无效的参考版本:
X.h:
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 是可复制的 and/or 可移动的,那么它就真的不是单例了。因此,通过从 class 中删除复制和移动操作来强制执行(默认情况下由编译器提供):
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
我想使用引用编写 Meyers Singleton class,但它不起作用。我似乎仍然在每次调用实例访问器方法时获得 class 的单独实例,即使打印表明构造函数只被调用一次。但是,如果我使用指针编写它,它就可以正常工作。谁能解释为什么以及如何修复参考版本?谢谢!
有效的指针版本:
X.h
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:
g++ -Wall X.cpp tryit.cpp && ./a.out
main
X constructor
i= 1
i= 2
i= 3
i= 4
无效的参考版本:
X.h:
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 是可复制的 and/or 可移动的,那么它就真的不是单例了。因此,通过从 class 中删除复制和移动操作来强制执行(默认情况下由编译器提供):
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