【问题标题】:Calling private destructor as deleter for std::shared_ptr using lambda?使用 lambda 调用私有析构函数作为 std::shared_ptr 的删除器?
【发布时间】:2013-02-10 19:17:54
【问题描述】:

对于这个游戏,我有一个 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();
}

如您所见,我的惰性初始化样式要求我使用智能指针,但是因为我试图避免使用公共析构函数,所以我必须使用 lambda 作为删除器,现在这段代码编译得很好,但是我似乎找不到任何模式来解释为什么标准所说的 lambda 是一个单独的唯一对象,可以调用这个私有方法,尤其是在查看了一些关于 SO 的问题之后:

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

【问题讨论】:

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


    【解决方案1】:

    标准在 5.1.2/3 中说

    lambda 表达式 [...] 的类型是唯一的 [...] 类类型 — 称为闭包类型 [...] 闭包类型在 包含的最小块作用域、类作用域或命名空间作用域 对应的 lambda 表达式。

    这意味着出现在(成员)函数内的 lambda 被视为本地类,在周围函数的块范围内声明。关于本地类,标准在 9.8/1 中说:

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

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

    如果 lambda 直接出现在类范围内,它将被视为嵌套类,适用类似规则:11.7/1 说:

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

    无论哪种方式,出现在类范围内的 lambda 都可以访问私有类成员。所以你的例子很好。

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-11-05
      • 2012-09-02
      • 1970-01-01
      • 2012-09-01
      • 2012-03-13
      • 1970-01-01
      • 2013-10-16
      相关资源
      最近更新 更多