为什么单例使用指针而不使用引用?

问题描述 投票:0回答:1

我想使用引用编写Meyers Singleton类,但是它不起作用。尽管打印显示构造函数仅被调用一次,但每次调用实例访问器方法时,我似乎仍会得到该类的单独实例。但是,如果我使用指针编写它,则效果很好。谁能解释为什么以及如何修复参考版本?谢谢!

适用的指针版本:

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
c++ singleton
1个回答
0
投票

X x1 = X::getX();正在复制单例实例。 X x2 = X::getX();也是。这意味着您实际上有[[0]个实例X。哎呀。怎么会这样这应该是single吨!如果单例类是可复制和/或可移动的,则它实际上不是单例。因此,可以通过从类中删除复制和移动操作(默认情况下由编译器提供)来表达这一点:

X(const X&) = delete; // Copy ctor X(X&&) = delete; // Move ctor X& operator=(const X&) = delete; // Copy assignment X& operator=(X&&) = delete; // Move assignment

完成此操作后,您会发现X x1 = X::getX();X x1 = X::getX();无法编译。好!编译器阻止您创建更多的X实例。通过使用引用来解决此问题:

X& x1 = X::getX(); X& x2 = X::getX();

并且所有工作正常:

main X constructor i= 1 i= 2 i= 3 i= 4

© www.soinside.com 2019 - 2024. All rights reserved.