How does “const” differ in C and C++?

后端 未结 2 1729
时光说笑
时光说笑 2020-12-14 03:44

How does the const qualification on variables differ in C and C++?

from: Does "const" just mean read-only or something more?

\"What prompted this q

相关标签:
2条回答
  • 2020-12-14 03:54

    const means that you promise not to mutate the variable. It could still be changed.

    class A {
      public:
        A(const int& a);
        int getValue() const;
        void setValue(int b);
      private:
        const int& a;
    };
    A::A(a) : a(a) {}
    int A::getValue() const {
        return a;
    }
    void A::setValue(int b) {
        a = b;  // error
    }
    
    int main() {
        int my_a = 0;
        A a(my_a);
        std::cout << a.getValue() << std::endl;  // prints 0
        my_a = 42;
        std::cout << a.getValue() << std::endl;  // prints 42
    }
    

    No method A::* may change a, but main can. That much is identical between C and C++.


    What C++ does have are a couple (limited) ways to bypass const, which are supposed to discourage programmers from discarding const inappropriately.

    Take a class like this.

    class A {
      public:
        A();
        int getValue();
      private:
        static int expensiveComputation();
        int cachedComputation;
    };
    
    A::A() : cachedComputation(0) {}
    
    A::getValue() {
        if (cachedComputation == 0)
            cachedComputation = expensiveComputation();
        return cachedComputation;
    }
    

    cachedComputation implicitly means this->cachedComputation. Keep this in mind.

    int main() {
        A a1;
        const A a2;
        std::cout << a1.getValue() << std::endl;
        std::cout << a2.getValue() << std::endl;  // error
    }
    

    a2.getValue() is illegal, because a non-const method is being called on a const A a2. One could cast away the const-ness…

        std::cout << ((A&)a2).getValue() << std::endl;            // C-style cast
        std::cout << const_cast<A&>(a2).getValue() << std::endl;  // C++-style cast
    

    The second is preferred, because the compiler will check that only the const-ness is being casted, nothing else. However, this is still not ideal. Instead, there should be a new method added to the class.

    class A {
      public:
        int getValue() const;
    };
    
    A::getValue() const {
        if (cachedComputation == 0)
            cachedComputation = expensiveComputation();  // error
        return cachedComputation;
    }
    

    Now there is a const method, so a2.getValue() is fine. However, the trailing const means that the method is given a const A *this pointer, not an A *this pointer like usual, making this->cachedComputation a const int & that cannot be mutated.

    const_cast could be applied inside the method, but better would be to change this one member's declaration.

    class A {
      private:
        mutable int cachedComputation;
    };
    

    Now, even with a const A *this, this->cachedComputation can be mutated without casting.

    0 讨论(0)
  • 2020-12-14 04:09

    const in C cannot be used to build constant expressions.

    For example :

    #include <stdio.h>
    int main()
    {
       int i = 2;
       const int C = 2;
       switch(i)
       {
          case C  : printf("Hello") ;
          break;
    
          default : printf("World");
       }
    }
    

    doesn't work in C because case label does not reduce to an integer constant.

    0 讨论(0)
提交回复
热议问题