【问题标题】:Check if instance exists and return reference in Singleton getInstance();检查实例是否存在并在 Singleton getInstance() 中返回引用;
【发布时间】:2012-07-26 13:49:49
【问题描述】:

我正在以first answer here. 中描述的方式实现单例,getInstance() 方法返回一个引用,但我不确定我应该如何创建我的新实例并在创建它之前检查它是否已经存在退货。

class Song {

private:
    Song song;
    Song();
    Song(Song const&); // don't implement
    void operator = (Song const&); //don't implement

public:
    static Song &getInstance();
}

那么我的getInstance(); 实现应该是什么样的?如果歌曲成员对象已经存在,我想返回它,否则创建它然后返回它。我知道我添加的链接中有一个 n 实现,但我不确定它是否符合我的要求,而且我不太了解它。

另外,有人可以解释这两行的用途以及为什么 = 运算符被覆盖吗?

    Song(Song const&); // don't implement
    void operator = (Song const&); //don't implement

【问题讨论】:

  • isn't first answer there 已经提供了 getInstance 的实现并回答了为什么将复制构造函数和赋值声明为私有?

标签: c++ singleton instance


【解决方案1】:

那么我的 getInstance();实现是什么样的?如果歌曲成员对象已经存在,我想返回它,否则创建它然后返回它。

这正是您链接的代码所做的。引用这个答案:

static S& getInstance()
{
    static S    instance; // Guaranteed to be destroyed.
                          // Instantiated on first use.
    return instance;
}

正如评论所说,它在第一次使用时被实例化;这就是函数范围内的静态变量的工作方式。

与实现 Singleton 反模式的这种特定尝试相关的致命陷阱是,在它被销毁后可以访问它,例如从另一个静态对象的析构函数中访问它。

另外,有人可以解释这两行的用途以及为什么 = 运算符被覆盖吗?

这些是为了防止复制对象。复制可以使用复制构造函数(创建新对象)或复制赋值运算符(覆盖现有对象)来完成;如果这些被声明为私有且未实现,则无法复制实例。在 C++11 中,可以通过删除它们来使其更加明确:

Song(Song const&) = delete;
void operator = (Song const&) = delete;

【讨论】:

  • 你能再告诉我一件事吗?我应该如何调用getInstance 方法?我试过song = Song::getInstance(); 但这不起作用..
  • @Sled:那是因为你试图复制它,这是不允许的。相反,您可以直接使用它,例如Song::getInstance().sing();,或者用它来初始化一个引用,例如Song & song = Song::getInstance();
  • 对,我明白了。谢谢你的解释。
【解决方案2】:

实现在您引用的答案中:

static S& getInstance()
{
    static S    instance; // Guaranteed to be destroyed.
                          // Instantiated on first use.
    return instance;
}

实例是静态的,所以它在第一次调用getInstance() 函数时被实例化。

更多信息请参见this related SO question

关于第二个问题的说明。首先是拷贝构造函数:

Song(Song const&);

如果要初始化一个对象以获取另一个对象的值,则需要它:

Song a;
Song b = a; // calls copy constructor

第二个是赋值运算符:

void operator=(const Song&);

需要为已经存在的实例赋值:

Song a;
Song b;
b = a; // calls assignment operator.

请注意,赋值运算符的标准返回值是一个引用:

Song& operator=(const Song&);

【讨论】:

  • 但这不是说我的实例每次都会重新创建吗?
  • @Sled 不,static 关键字表示 instance 是为每次调用创建的唯一一个。您可以在多次调用的函数中使用static int 变量,看看它是如何工作的。
  • 所以这也意味着我不需要将对象添加为成员,因为我有一个内部带有静态对象的静态函数?
  • @Sled 确切地说,该对象从第一次调用到程序终止都存在,因此它不能是普通数据成员。但请阅读 Mike Seymour 的回答,了解这种方法的缺陷。
【解决方案3】:

为了回答第二个问题,这两行将复制构造函数和赋值运算符声明为私有,因此它们不能被调用。如果没有这两行,编译器将生成这些的默认实现,客户端可以创建副本,从而违背了Singleton 模式的目的。

【讨论】:

    猜你喜欢
    • 2017-04-28
    • 2019-01-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-06-26
    • 1970-01-01
    相关资源
    最近更新 更多