【问题标题】:Private members: Static const vs. just const私有成员:静态 const 与仅 const
【发布时间】:2009-12-21 00:01:57
【问题描述】:

我正在尝试确定当一个对象具有一些不会改变的特征并且在其整个功能中都需要时,最佳选择是什么。

  1. 静态常量成员
  2. Const 成员

在我看来,静态成员的真正原因是拥有一个可以更改的变量,从而影响同一类的所有其他对象。但是,我有人推荐类“不变量”是静态常量成员。我正在寻找有关建立类常量的推荐方法及其原因的一些见解。

【问题讨论】:

    标签: c++


    【解决方案1】:

    const 成员应在该成员不基于每个实例更改时使用。 static const 成员应在该成员不按类更改时使用。换句话说,无论您创建多少个实例,static const 成员在所有实例之间保持固定,而 const 成员仅对于特定实例是恒定的。

    我不确定这是否是您要查找的内容,因为这只是对它们行为方式的解释,但我希望它有所帮助。

    【讨论】:

      【解决方案2】:

      “不会改变”不够精确。这里的主要问题是类的不同对象是否需要具有这些 const 成员的不同值(即使它们在对象的生命周期内不会改变),还是所有对象都应该使用(共享)相同的值。

      如果类的所有对象的值都相同,那么它当然应该是类的static const 成员。

      如果不同的对象可能需要不同的值,那么它应该只是一个非静态的const 成员。

      【讨论】:

      • “不会改变”我的意思是类的所有对象的值都是相同的。
      • 在这种情况下,您没有理由不这样做static const。非静态 const 也可以(除了一些特定/特殊情况),但会导致完全不必要的内存浪费。
      • @AnT 您在评论中自相矛盾,如果该值对于该类的所有对象都相同,则无论成员是否为“const”,它都必须是“静态”。尽管如此,我同意答案(但不同意您的评论)
      【解决方案3】:

      一个原因是常规的 const 成员会占用更多内存...即,对于您创建的类的每个对象,一个 const 成员对象将包含在该对象中并被初始化。

      另一方面,如果它是静态 const 成员,那么无论您创建多少类的对象,都只会创建和初始化一个对象,并且所有类对象都将共享同一个对象。

      为了演示,尝试两种方式编译它,创建几个对象,然后执行 printf("%p", &theConstMemberObject)... 当它是静态的时,你会看到它们都打印相同的指针值;当它不是静态的时,它们每个都有自己的对象,因此它们每个都打印不同的指针值。

      【讨论】:

        【解决方案4】:

        您将创建一个成员变量 static const,因为它不变,您可以重用它的相同副本,由您的类的所有实例共享。与每个实例都有自己的(相同的)常量值副本相反。

        您会期望编译器足够聪明,可以为您执行此优化,我怀疑确实如此。不过,这是一个很好的习惯。

        【讨论】:

        • 一个 const 成员变量可以在构造函数中初始化,因此可能因类的不同实例而异。
        • 你必须小心你可以假设编译器为你做什么。正如@danio 指出的那样,如果在不同的编译单元中重用标头,则只有一个编译单元可以让编译器知道该值是共享的,而不是许多必须定义兼容的内存布局的编译单元。知道的人不能改变内存布局,因为它会破坏所有其他编译单元中的代码。
        【解决方案5】:

        我的偏好是不使用static const 成员,因为它似乎总是比const 成员产生更多的耦合;有时会混淆 w.r.t 菱形继承层次结构,其中最终类继承自 2 个超类(1 个类继承 public;另一个继承 virtual public)然后定义一个 static const 成员,该成员通过 new 指向动态内存区域、malloccalloc 等会导致 double free 错误。

        例如这是一个简单的钻石继承情况的输出

        ray:~ ray$ ./multiinheritance 
        Base() called 
        Derived1() called 
        Base() called 
        Derived2() called 
        Final() called
        ~Final() called
        ~Derived2() called
        ~Base() called
        freeing memory
        ~Derived1() called
        ~Base() called
        freeing memory
        multiinheritance(475) malloc: *** error for object 0x100150: double free
        *** set a breakpoint in malloc_error_break to debug
        ray:~ ray$ 
        

        代码如下:

        #include <iostream>
        #include <string>
        
        class Base {
        public:
            Base() {
                std::cout << "Base() called " << std::endl;
            }
            virtual ~Base() {
                std::cout << "~Base() called" << std::endl;
                std::cout << "freeing memory" << std::endl;
                delete i;
            }
            static const int* i;
        };
        
        const int* Base::i = new int[5];
        
        class Derived1 : virtual public Base {
        public:
            Derived1() {
                std::cout << "Derived1() called " << std::endl;
            }
            virtual ~Derived1() {
                std::cout << "~Derived1() called" << std::endl;
            }
        };
        class Derived2 : public Base {
        public:
            Derived2() {
                std::cout << "Derived2() called " << std::endl;
            }
            virtual ~Derived2() {
                std::cout << "~Derived2() called" << std::endl;
            }
        };
        
        class Final: public Derived1, public Derived2 {
        public:
            Final() {
                std::cout << "Final() called" << std::endl;
            }
            ~Final() {
                std::cout << "~Final() called" << std::endl;
            }
        };
        
        int main(int argc, char** argv) {
            Final f;
        return 0;
        }
        

        【讨论】:

        • 您应该发布获得该输出的代码,否则它是无用的。而且我不太确定它是否有用,因为我看不到conststatic const 会在哪里产生影响。从您给出的描述来看,这听起来更像是staticnon-static 动态内存分配和删除的问题。
        • @dribeas,我试图说明有时将conststatic const 与多重/虚拟继承混合
        猜你喜欢
        • 1970-01-01
        • 2011-10-22
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-07-09
        • 2012-12-13
        相关资源
        最近更新 更多