2

下面是单例类的代码


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

后者是所需的输出。这是因为设计问题还是用户编码问题造成的异常?如何确保只获得第二个结果?

谢谢

4

3 回答 3

10

T x = foo()制作副本。

或者表现得“好像”它做了一个副本。

While T& x = foo(),当foo返回一个T&引用时,只做一个引用。


将复制构造函数和复制赋值运算符设为私有。这将阻止人们全部复制。将复制赋值运算符设为私有可防止自复制。

从 . 返回指向单例的指针不是替代方法getInstance。这将是一种让人们不知道始终存在实例的保证的万无一失的方式。指针表示它可以是空指针。

但是,如果可以避免,最好的选择是不使用单例。单例有很多问题。这些问题包括生命周期管理、线程安全以及与检测内存泄漏的工具的交互。

于 2011-11-02T02:15:18.963 回答
2

删除复制构造函数(使其私有)。这将阻止人们复制。

另一种选择是为 getInstance() 返回一个指向单例的指针。这将是让人们知道他们引用了单例的可靠方法。

第三种选择是在共享数据周围有一个可复制的包装类。该包装器将具有指向单例的指针等,并且是可复制的。

于 2011-11-02T02:07:15.797 回答
2

您正在正确返回对单例变量的引用,但问题在于您分配给它的内容。

这段代码:

single d1 = single::getInstance();

方法:

创建一个类型的新变量single并复制返回的引用以对其进行初始化。因此,每次执行此操作时,您都在创建一个新变量,而不是使用单例变量。

这段代码:

single & d1 = single::getInstance();

方法:

创建对与返回引用相同的变量的新引用。因此,每次执行此操作时,您都会根据需要获得对单例变量的引用。

为了阻止你自己(和其他人)犯这个错误,你应该将你的构造函数设为私有。

于 2011-11-02T02:11:02.467 回答