Home  >  Q&A  >  body text

c++ - 关于const_cast的几点疑问

来自《c++primer第5版》,我的疑问是粗体:

const_cast

  const_cast只能改变运算对象的底层const

const char *pc; 
char *p=const_cast<char*>(pc);//正确:但通过p写值是未定义的后果

对于将常量对象转换成非常量对象的行为,我们一般称其为“去掉const性质”。一旦我们去掉了某个对象的const性质,编译器就不再阻止我们对该对象进行写操作了。如果对象本身不是一个常量,使用强制类型转换获得写权限是合法的行为。
上面这句话是什么意思?是说

char *pc;
const char *p=const_cast<const char*>(pc);

用来对p写值是合法的行为吗?我觉得反过来才对吧?(我已经懂了,作者意思应该是说非常量constcast 成常量后再const cast成非常量的这种情况是可以获得写权限的)

然而如果对象是一个常量,在使用const_cast执行写操作就会产生未定义的后果。
我想const_cast的目的就是用来对const对象写值,如果“通过p写值是未定义的后果”那么使用const_cast有什么用呢?

PHPzPHPz2715 days ago712

reply all(2)I'll reply

  • 阿神

    阿神2017-04-17 12:07:39

    For the behavior of converting a constant object into a non-constant object, we generally call it "removing the const property". Once we remove the const nature of an object, the compiler no longer prevents us from writing to the object. If the object itself is not a constant, it is legal to use a cast to gain write access.

    What does the above sentence mean?

    Answer: Even if const_cast can remove the constness of a pointer or reference (go to const) and obtain a non-const pointer or reference, using the converted pointer or reference to modify an object originally declared as const will cause unforeseen consequences. Define behavior. Example

    const int j = 3; // j 声明为const常量
    int* pj = const_cast<int*>(&j);  
    *pj = 4;         // 用去const的指针去修改一个原本就是常量的j的值,undefined behavior!

    If j is declared as int j = 3; it is not a constant, the above code is legal and expected to work.

    I think the purpose of constcast is to write values ​​to const objects. If "writing values ​​through p is an undefined consequence", then what is the use of using constcast?

    Answer: The following uses:

    1. The most common thing is that when some people declare a function type, they do not declare it as const even if the value of the pointer is not modified in the function. This is typical laziness, such as
      void log(char* msg);
      Obviously it is just used to print out msg, but it does not add const. In this case, we have to convert the const pointer on our hand to non-const and then pass it to it, because the c++ compiler does not allow you to directly throw the const pointer to char*, and an error will be reported, while c compilation, such as gcc, only generates Just a warning.

    2. I saw this usage in effective c++, sample code:

    class MyClass
    {
        char cached_data[10000]; // should be mutable
        bool cache_dirty;        // should also be mutable
    
      public:
    
        char getData(int index) const
        {
            if (cache_dirty)
            {
              MyClass* thisptr = const_cast<MyClass*>(this);
              update_cache(thisptr->cached_data);
            }
            return cached_data[index];
        }
    };

    In short, in a const member function, you need to modify the member variables that are not declared as mutable.

    1. You can remove volatile-modified variables. The specific function remains to be understood.


    It is also said above that "Only const_cast can change the constant attribute of an expression. Using other forms of named cast to change the constant of an expression will cause a compiler error." However, the following example is

    static_cast<string>(cp);//正确:字符串字面值转换成string类型

    Isn’t this a contradiction?

    First of all

    Only const_cast can change the constant attribute of an expression. Using other forms of named casts to change the constant of an expression will cause a compiler error

    This sentence means that to convert an expression from const to non-const, or vice versa, only const_cast can be used, and other forms such as

    static_cast<char*>(cp);

    This won’t work.

    Then

    Cannot use const_cast to change the type of expression

    This sentence means that when using const_cast, the type to be converted and the type being converted must be consistent. The only difference is whether there is a const modifier, such as

    const_cast<string>(cp);

    This is not possible because the type of cp is char*, which is completely different from string. If cp is const string cp, it will work.

    But
    staticcast<string>(cp) is feasible because it does not change const, it just changes the type, which does not fall into the two situations mentioned above with constcast.

    In fact, the content of the book is condensed, and the codes are put together to save space, which leads to misunderstanding.

    reply
    0
  • 大家讲道理

    大家讲道理2017-04-17 12:07:39

    First of all, whether the const modifier is added or not will constitute operator overloading. The counterpart to const is volatile, collectively called the cv modifier.
    I think the purpose of constcast is to write values ​​to const objects. If "writing values ​​through p is an undefined consequence", then what is the use of using constcast?
    const_cast is just a compile-time convention, and "writing values ​​through p is an undefined consequence" is a runtime problem. These two constraints are not the same thing
    It was also said above" Only const_cast can change the constant attributes of an expression. Using other forms of named casts to change the constants of an expression will cause a compiler error." However, the following example is
    Your example is correct because You used static_cast to convert

    #include <stdio.h>
    #include <iostream>
    using namespace std;
    #include <string>
    using std::string;
    
    class MyClass
    {
    public:
        void test()
        {
            cout << "none const object"<<endl;
        }
        void test() const
        {
            cout << "const object" << endl;
        }
    
        void test() volatile
        {
            cout << "volatile object" << endl;
        }
    };
    
    int main()
    {
        MyClass *a = new MyClass();
        const MyClass *b = new MyClass();
        volatile MyClass *c = new MyClass();
        a->test();
        b->test();
        c->test();
        MyClass *d = 0;
        // d = b; 编译会报错,无法去掉const属性,需要
        d = const_cast<MyClass*>(b);
        d->test();
        system("Pause");
        return 0;
    }

    reply
    0
  • Cancelreply