代码之家  ›  专栏  ›  技术社区  ›  Romain Hippeau

C++中的“哨兵对象”是什么?

  •  14
  • Romain Hippeau  · 技术社区  · 16 年前

    answered question Potatoswatter answered 也一样

    现代的C++等价物将是 哨兵目标:在 函数的开头,及其 构造函数实现call(),和 返回(或异常退出)时, 析构函数实现

    我不熟悉在C++中使用哨兵对象。 我认为它们仅限于输入和输出流。

    有人可以向我解释C++的StEnter对象以及如何将它们作为类中的一个或多个方法的截取器来使用吗?

    也就是说,如何做到这一点?

    哨兵的物品非常相似 的确。一方面,他们需要 显式实例化 但另一方面你 可以添加到它们,以便它们不检查 只有类的不变量,但是 一些前/后条件 手边的功能。

    3 回复  |  直到 10 年前
        1
  •  16
  •   Community Mohan Dere    9 年前

    哨兵的目标是一个模式,但我不确定下面哪一个(也许全部)。

    当一个对象(可能是用户定义的类)被破坏时,即当它的析构函数被调用时,C++程序常常严重依赖于知识。对于使用垃圾收集的语言来说,情况并非如此。

    例如,此技术用于采用“资源获取即初始化”范式:当调用对象构造函数时获取资源,编译器自动调用其析构函数以释放正常和异常(异常)情况下的资源(检查 this question )

    您可以利用构造/破坏时间知识的常见地方有

    • 阻碍 :在块的末尾调用“stack allocated”对象的析构函数

      void function()
      {  Class foo = Object(resource);
         other_operations();
      }  // destructor for foo is called here
      
    • 函数调用 :“堆栈分配”在调用函数时也会发生

      void function()
      {  another_function ( Class(resource)  );
         // destructor for the unnamed object is called
         // after another_function() returns (or throws)
         other_operations();
      }
      
    • 包含对象的构造/销毁 :

      class Foo
      {  Class sentry;
         public: Foo()
         { // Constructor for sentry is called here
            something();
         }        
         public: ~Foo()
         {
            something();
         }  // destructor for sentry is called here
      };
      

    在STL中有一个类叫做 sentry (更确切地说, istream::sentry ,这实现了上述模式的第三种模式。所以我认为这就是一些程序员所说的“哨兵对象”。

    但事实上,上述任何一个类的对象 Class 可称为“哨兵对象”。他们是“哨兵”,因为他们确保即使有什么东西抛出异常,也不会错过这些难以捉摸的对象析构函数(所以他们类似于块/类的守护者)。

    更多的哨兵目标例子 RAII question .


    您可以看到与面向方面编程的关系;这些对象类似于“方面”,其切点“在封闭块的开始/结束处”、“在包含对象的构造/销毁处”等,但这些“方面” 不得不 存在于他们所期望的代码中。所以和原来的相比,它们没有那么“完美” call/return 功能性;相反,应在类的每个函数中插入一个Sentry对象:

    class X{
      struct Sentry {
         Sentry() { /* call() */}
        ~Sentry() { /* return() */};
      };
    
      void member_function()
      { Sentry();
        /* operations */
      }
    
      void another_member_function()
      { Sentry();
        /* operations */
      }
    };
    
        2
  •  3
  •   fa.    16 年前

    与AOP不同的是,它必须完成 合作地 通过将哨兵显式地放在函数体或类定义的某个地方。

    如果不修改目标函数或类,则无法捕获调用。

        3
  •  2
  •   Community Mohan Dere    9 年前

    Here 是Sentry类的一个示例,它将变量重置为其旧值。