【问题标题】:Do you declare your module specific functions as static?您是否将模块特定功能声明为静态?
【发布时间】:2010-09-23 19:06:26
【问题描述】:

我认为将它们声明为静态是最佳实践,因为它使它们在模块之外不可见。

您对此有何看法?

【问题讨论】:

    标签: c++ c static function


    【解决方案1】:

    对于 C++,比静态更好的方法是将其放在未命名(匿名)的命名空间中。这是防止全局命名空间污染的首选方法。

    namespace {
    void myLocalFunction() {
    // stuff
    }
    }
    

    【讨论】:

    • 匿名命名空间的另一个优点是您仍然可以将其中的对象的地址传递给模板,因为它们仍然具有外部链接。
    • +1,在这个 SO 线程中找到更多信息:stackoverflow.com/questions/154469/…
    • 缺点是在 C 中没用。问题是关于 c/c++
    • 我没有注意到 C 标签。这是一个仅限 C++ 的解决方案。
    • 不完全弃用,它将继续工作。但是命名空间是一种更好的方式,推荐用于任何新代码。
    【解决方案2】:

    如果它确实是一个仅在该 .c 文件内部的函数,那么是的。它应该有助于避免污染全局命名空间。另外,我认为如果函数是静态的,编译器可以对调用约定进行一些优化,因为它不知道其他源文件需要知道如何调用它。这仅适用于 c,因为正如其他人所指出的,c++ 有命名空间来解决这个问题。

    【讨论】:

      【解决方案3】:

      关于实现细节的内容很多,关于概念的内容不多。

      限制变量/函数等的范围确实是一个好习惯。这是面向对象设计的基本概念——您希望将私有作为私有。这样你的界面更干净,代码维护更容易。而且您不会发现有一天更改您认为是私有的破坏编译的东西,因为项目的另一部分中的某个人喜欢您的功能并决定使用它。

      【讨论】:

        【解决方案4】:

        在 C 语言中,我在文件范围内将所有内容(函数和变量)设为静态,直到我可以证明它们在文件之外是必需的。如果只有那个函数会使用它们并且它们不是太大,我会在一个函数中使它们成为静态的。基本上,如果声明大于函数的其余部分,我可以将声明放在函数之外。当然,还有一个源文件提供的公共服务的标头。

        【讨论】:

        • 在可重入和多线程方面,应该小心在函数中使用静态。
        • @Ilya:同意。我尽量让事情变得 const 。碰巧我的大部分工作都不涉及线程。但是,我尽量避免使用全局变量;我还尽量避免在文件和函数范围内使用静态变量。
        【解决方案5】:

        同意。因此,静态函数的原型必须放在 .c 文件的顶部,而不是 .h 文件中。

        【讨论】:

          【解决方案6】:

          在 C++ 中,您应该使用匿名命名空间,如下所示:

          // foo.cpp
          namespace
          {
             class Core { ... };
             void InternalFandango(Core *);
          }
          
          void SomeGloballyVisibleFunction()
          {
             InternalFandango(&core);
          }
          

          优点:这也适用于结构/类声明。
          在 C 中,只需将函数标记为“静态”。在 C++ 中也没有反对使用“静态”,但我学会了更喜欢命名空间,因为它是一个适用于所有声明的单一概念。

          【讨论】:

            【解决方案7】:

            我认为 C 和 C++ 对static 有不同的限制:在 C 中,您没有命名空间,而 .c 文件是您的模块,因此将所有非公共函数设为静态以防止错误非常重要!

            【讨论】:

              【解决方案8】:

              关于在 C++ 中使用“静态”,我能想到的唯一可能有用的属性是匿名命名空间不提供的,那就是 GCC 中有一个警告,您可以打开未使用的静态函数(一种死代码)。对于匿名命名空间中未使用的函数,您不会得到这样的信息,因此,如果您希望编译器在您停止使用该函数时告诉您,那么就这样做吧。

              【讨论】:

                【解决方案9】:

                在 C 代码中,默认情况下将您的函数设为静态。只为其他模块需要的函数创建非静态函数和 .h 声明。

                在 C++ 代码中,将文件本地的那些函数放入匿名命名空间使它们成为静态的。至少在 GNU 编译器中,这将产生最好和最小的代码,因为如果所有使用都内联,则不会编写任何函数。如果您打算将其内联,那么将其标记为内联当然比静态更好。

                我不知道为什么 g++ 将匿名命名空间中未调用的函数体写入输出,但确实如此。隐藏可见性的功能似乎也出现了;标记为隐藏符号,但仍会在目标文件中产生未使用的代码块。 GCC 可能不明白在这些情况下不需要代码。或者我错过了什么,总是有可能的。

                【讨论】:

                • 您所描述的一定是 GCC 错误,我无法复制。虽然这对于当时使用该编译器的人来说可能是有用的信息,但将其推断为同时使用namespace {static 的一般建议是没有意义的。正确的做法是提交错误,而不是让您和其他人的代码使用从语言角度来看没有意义的样板文件。
                【解决方案10】:

                如果您使用的是 GCC,那么您应该查看可见性标志(有关完整讨论,请参阅 http://gcc.gnu.org/wiki/Visibility)。

                它将完全隐藏符号,而不是将它们标记为不可访问。这减少了符号表,并有助于减少链接时间。

                不仅如此,它还为更多内联打开了大门,如果这是您所追求的。

                【讨论】:

                  【解决方案11】:

                  如果“模块”只是指 CPP 文件,则可以将声明和定义直接放在 CPP 文件中。

                  【讨论】:

                  • 这并不能真正阻止生成外部符号,因此它仍然可能与另一个“模块”中的符号冲突
                  【解决方案12】:

                  在 C++ 中,您可以像这样声明函数私有:

                  class MyClass
                  {                           
                  public:                 
                  void publiclyAccessibleFunction();            
                  private:                
                      void onlyAccesibleFromWithinTheClass();
                  int some_member_parameter;          
                  };
                  

                  注意onlyAccesibleFromWithinTheClass() 函数。

                  【讨论】:

                  • OP 讨论的是模块,即单独编译的源文件及其头文件,而不是对象。
                  猜你喜欢
                  • 1970-01-01
                  • 2013-11-19
                  • 2014-05-12
                  • 2011-01-23
                  • 1970-01-01
                  • 1970-01-01
                  • 2021-01-19
                  • 1970-01-01
                  • 1970-01-01
                  相关资源
                  最近更新 更多