【问题标题】:What's your convention for typedef'ing shared_ptr?你对 typedef'ing shared_ptr 的约定是什么?
【发布时间】:2011-02-12 15:08:51
【问题描述】:

我在 typedef'ing boost::shared_ptr 模板的命名约定之间来回切换。例如:

typedef boost::shared_ptr<Foo> FooPtr;

在确定约定之前,我想看看其他人使用什么。你的约定是什么?

编辑:

对于那些将typedef 嵌套在Foo 中的人,Foo 现在“知道”它是如何被传递的,你不会感到困扰吗?它似乎打破了封装。这个怎么样:

class Foo
{
public:
    typedef std::vector<Foo> Vector;
};

你现在不会这样做,对吗? :-)

【问题讨论】:

  • 补充这个问题,当你声明这样一个 typedef 时,人们如何管理标题包含?这不会导致每个人都必须包含 Foo.h(而不仅仅是说“class Foo;”),从而导致构建缓慢并可能导致循环依赖?
  • 如果您使用工厂,我认为嵌套的 typedef 不会破坏封装。事实上,我会说在这种情况下它会改进封装,以防指针类型发生变化。
  • @RobNapier #include "foo_ptr.hpp" ;-)
  • @RobNapier 我调用宏MYLIB_DECLARE_PTRS(Foo); 来替换class Foo;。灵感来自convention used in Pixar's USD --- 我喜欢这个大会。

标签: c++ boost naming-conventions shared-ptr


【解决方案1】:

我也想为这个老问题添加一些选项,即使它们可能会引起很大争议……

类似于OldPeculier's answer 我喜欢尽可能接近标准指针的短类型名称。

在一个几乎到处使用shared_pointer 的项目中,我使用了

typedef boost::shared_ptr<Foo> Foo_;

// usage examples:
Foo* myFoo0;
Foo_ myFoo1;

我利用了三件事:

  1. 下划线字符在某种程度上看起来像一个运算符,但主要被视为一个字母,因此它可以成为标识符的一部分(我在标识符的末尾看到no rule forbidding它)。
  2. 我只需要想出一个 typedef。
  3. 我更喜欢 Foo* myFoo1; 而不是 Foo *myFoo1; 有几个原因,它与 Foo_ myFoo2 非常匹配。

当需要不同类型的智能指针的 typedef 时,我会选择

typedef shared_ptr<Foo> Foo_S;
typedef weak_ptr<Foo>   Foo_W;
typedef unique_ptr<Foo> Foo_U;

// usage examples:
Foo*  myFoo2;
Foo_S myFoo3;
Foo_W myFoo4;
Foo_U myFoo5;

随着标准和编译器实现中对 Unicode 支持的增加,我很想尝试以下语法,假设这些星号将被视为类型标识符的常规部分。当然,这只有在所有相关的开发人员都有一个方便的文本输入法时才实用:

typedef shared_ptr<Foo> Foo★;
typedef weak_ptr<Foo>   Foo☆;
typedef unique_ptr<Foo> Foo✪;

// usage examples:
Foo* myFoo6;
Foo★ myFoo7;
Foo☆ myFoo8;
Foo✪ myFoo9;

(快速测试表明这实际上不起作用,至少在我的构建环境中是这样。但Foo_ä 也是如此。)

【讨论】:

  • 作为这个答案的作者,我想透露我在推特上发布了一个链接,上面有最后一个代码示例的截图。由于代码的搞笑外观,这条推文获得了很高的人气——超过 150 次转发和超过 50.000 次观看——因此相对较高的点赞数可能并不具有代表性。
  • 请注意,int* a, b 可能看起来像 a 和 b 都是指向 ints 的指针。然而,情况并非如此:只有a 是int 的指针,b 只是int。这就是为什么我更喜欢int *a, b,它(可能)有助于避免混淆。还有一件事:如果您有typedef int *PTR_INT; 和PTR_INT a, b,那么a 和b 都是PTR_INT,即指向ints 的指针。
【解决方案2】:

回答:不要这样做。这对您和其他人都很方便。说出你的意思。

【讨论】:

  • 是的,我同意。在这种情况下,Typedef'ing 只会节省您的打字时间,而不是其他任何事情。它只是为理解代码增加了一种间接性。
【解决方案3】:

我的偏好:

class Foo
{
public:

    typedef boost::shared_ptr<Foo> SharedPointer;
};

FooPtr 的问题在于您可能有不同类型的指针(例如,weak_ptrs)。我也不太在意缩写,但这完全是另一回事。

【讨论】:

  • 正如它在 cmets 中所指出的,这会导致包含标头的问题。如果不包含Foo.h,您将如何在头文件中使用Foo::SharedPointer?
【解决方案4】:

就个人而言,在我负责的代码中,您通常会在与 Foo 相同的命名空间范围内看到 FooPtr typedef'd 并且 Foo 将包含一个通用命名为“SmartPtr”的 typedef与 FooPtr 相同的类型。拥有 FooPtr 可以轻松进行非冗长的手动使用。拥有 'SmartPtr' 的嵌套 typedef 或某些等效项允许在模板、宏等中轻松泛型使用,而无需知道智能指针的实际类型。

另外,我建议在这个问题中添加一个“主观”标签。

【讨论】:

【解决方案5】:

我已经使用了外部和封装的typedef,但最终还是使用了第一个,

typedef boost::shared_ptr<Foo> FooPtr; 

仅仅因为在组合表达式中这看起来比Foo::Ptr 更干净。

Foo 现在“知道”它是如何被传递的,你不介意吗?

通常,这些类只能通过工厂方法创建:

struct Foo
{
     static FooPtr Create() { return FooPtr(new Foo); }

   protected:
     Foo() {}
}

这比封装 typedef 更“强大”,但也是一种非常常见的模式。

【讨论】:

    【解决方案6】:

    我通常不喜欢非常短的标识符,但这是我将使用它们的一种情况。

    class Foo
    {
    public:
        typedef std::shared_ptr<Foo> p;
    };
    

    这使得 shared_ptr 尽可能地类似于普通指针,而不会造成混淆。

    Foo* myFoo;
    Foo::p myFoo;
    

    至于打破封装——不,在类中定义 shared_ptr 类型并不会破坏封装,就像在类外部定义它一样。它会违反“封装”的什么含义?您没有透露有关 Foo 的实施的任何信息。你只是在定义一个类型。这完全类似于 Foo* 和 Foo 之间的关系。 Foo* 是某种指向 Foo 的指针(碰巧是默认类型)。 Foo::p 是另一种指向 Foo 的指针。你没有破坏封装,你只是添加到类型系统中。

    【讨论】:

      【解决方案7】:

      我不是匈牙利命名约定的忠实拥护者,我通常使用:

      typedef boost::shared_ptr<Foo> FooSharedPtr;
      

      足够详细,清晰,但又足够短,不会造成太大的麻烦。无论如何,我肯定会指出它是一个共享指针,特别是如果你不是唯一一个将来会使用该类型的人。

      【讨论】:

        【解决方案8】:

        我通常将typedef 封装在类中。原因是我们有一些内存敏感的代码,它可以很容易地在boost::shared_ptr 和boost::intrusive_ptr 之间切换 因为intrusive_ptr 是类需要支持的东西,所以知道要使用哪个共享指针被封装在类中对我来说很有意义。

        【讨论】:

          【解决方案9】:

          我的第一反应是问,“为什么 typedef 那个?”

          回复您的编辑:实际上,这是一种相当有趣的方法,在许多情况下都可能有用。使用它返回您可能遇到的原始问题:

          
          struct object
          {
            typedef object* ptr_t;
            typedef shared_ptr<object> shared_ptr_t;
            typedef weak_ptr<object> weak_ptr_t;
            typedef unique_ptr<object> unique_ptr_t;
            etc...
          }
          

          【讨论】:

            【解决方案10】:
              typedef shared_ptr<Foo> sptr_Foo;
              typedef weak_ptr<Foo>   wptr_Foo;
              typedef unique_ptr<Foo> uptr_Foo;
            

            【讨论】:

              【解决方案11】:

              以_t结尾很好。

              class Bar
              {
              public:
                  typedef boost::shared_ptr<Bar> Ptr_t;
              };
              

              【讨论】:

              • 不,不是。以_t 结尾的名称是reserved 用于实现。
              • 无赖。这对我来说是一个真正的惊喜,而且相当不愉快。
              • @LoganCapaldo 仅当您在 POSIX 系统上编程时。
              【解决方案12】:

              这是我所遵循的约定之一:

              typedef boost::shared_ptr<Foo> FooProxy;
              

              ...看到boost::shared_ptr 是Proxy 模式的一个应用程序。

              【讨论】:

                【解决方案13】:
                class foo;
                
                typedef boost::shared_ptr<foo> foo_p;
                typedef boost::weak_ptr<foo> foo_wp;
                

                【讨论】:

                  【解决方案14】:

                  typedef boost::shared_ptr&amp;lt;MyClass&gt; MyClass$;

                  【讨论】:

                    【解决方案15】:

                    怎么样:

                    template <typename T>
                    class Shared
                    {
                        public: 
                            typedef std::shared_ptr<T> Ptr; // or boost::shared_ptr if you will
                    };
                    

                    然后允许任何Shared 类拥有自己的 Ptr 对象,如:

                    class myClass : public Shared<myClass>
                    {
                    };
                    
                    int main()
                    {
                        myClass::Ptr object;
                        //...
                        object->foo();
                    }
                    

                    【讨论】:

                      【解决方案16】:

                      我会摆脱命名空间而不是缩短类型。

                      using boost::shared_ptr; // or using std::shared_ptr, 
                      struct Foo
                      {
                          shared_ptr<Foo> impl;
                      };
                      

                      它的好处是您可以轻松地在实现之间进行更改。

                      如果还是太长(我觉得刚刚好):

                      using boost::shared_ptr;
                      template<class T> using sptr = shared_ptr<T>;
                      struct Foo
                      {
                          sptr<Foo> impl;
                      };
                      

                      【讨论】:

                        猜你喜欢
                        • 2023-03-04
                        • 1970-01-01
                        • 2010-11-16
                        • 2015-03-04
                        • 1970-01-01
                        • 1970-01-01
                        • 2013-10-11
                        • 1970-01-01
                        • 2013-07-06
                        相关资源
                        最近更新 更多