使用lambda调用私有析构函数作为std :: shared_ptr的删除器?

时间:2013-02-10 19:17:55

标签: c++ memory-management c++11 lambda anonymous-function

对于这个游戏,我有一个Game类,它是一个单例...这是头文件

#ifndef SOKOBAN_GAME_H
#define SOKOBAN_GAME_H
#include <memory>
#include <SDL/SDL.h>
namespace sokoban
{
  class Game
  {
  public:
    static Game* getInstance();
    void startGame();
  private:
    Game();
    ~Game();
    Game(const Game&) = delete;
    Game(Game&&) = delete;
    Game& operator=(const Game&) = delete;
    Game& operator=(Game&&) = delete;

    static std::shared_ptr<Game> instance_;
    SDL_Surface* mainSurface_;
  };
};
#endif

现在,除了getInstance函数之外,大多数实现文件都不重要:

Game* Game::getInstance()
{
  if(!Game::instance_)
  {
    Game::instance_ = std::shared_ptr<Game>(new Game,
    [](Game* ptr)
    {
      delete ptr;
    });
  }

  return Game::instance_.get();
}

正如你所看到的,我的lazy-initialize样式要求我使用智能指针,但是因为我试图避免使用公共析构函数,所以我必须使用lambda作为删除器,现在这段代码编译得很好,但是我似乎无法找到任何模式为什么一个lambda,由标准称为一个单独的独特对象,可以调用这个私有方法,特别是在查看SO上的一些问题之后:

我基本上想知道的是成员函数中lambda的访问规则,如示例...

1 个答案:

答案 0 :(得分:3)

标准在5.1.2 / 3中说明

  

lambda-expression [...]的类型是一个独特的类类型 -   调用闭包类型[...]闭包类型在声明中声明   包含的最小块范围,类范围或命名空间范围   相应的lambda表达式。

这意味着在(成员)函数内发生的lambda被视为本地类,在周围函数的块作用域中声明。关于本地课程,标准在9.8 / 1中说:

  

[...]本地类属于封闭范围的范围,并且具有   对函数外部的名称的访问与封闭的名称相同   功能。[...]

因此lambda具有与包含成员函数相同的访问权限,这意味着它可以访问该类的私有成员。

如果lambda直接出现在类作用域中,它将被视为嵌套类,适用类似的规则:11.7 / 1表示:

  

嵌套类是成员,因此具有相同的访问权限   任何其他成员。

无论哪种方式,在类范围内发生的lambda都可以访问私有类成员。所以你的榜样很好。

(您提到的帖子,最终是关于访问由 qualified-id 命名的基类的受保护成员的问题。)