• C++ Const总结


    一、const_cast


    来自MSDN的说明

    一个指向对象或对象成员的指针可以显式地转换为带有不同const、volatile或__unaligned属性的同一类型。对于指针和引用,转换结果引用的是原对象。对指向数据成员的指针,转换结果指向原指针(转换前)指向的对象。通过转換得到的指针、引用及(指向数据成员的)指针来进行写操作可以导致未定义的行为——取决于引用对象的类型。

    const_cast会将一个空指针转换为一个目标类型的空指针。

    总结:

    const_cast只能应用于指针或引用类型。似乎从语义上,const_cast只允许重新解释原对象,而避免产生对象的副本。这很好理解:倘若我们要取消某个对象的const属性,多半是为了更改它。如果const_cast产生副本,便人是物非一场空了。

    return const_cast<TestConstReload>(*this).v;      //error C2440: 'const_cast' : cannot convert from 'const class xx' to 'class xx',对于内置类型同样如此
    return const_cast<TestConstReload&>(*this).v;   //OK
    return const_cast<TestConstReload*>(this)->v;   //OK


    二、const重载

    对于成员函数,可以有相同参数列表,但函数本身的const属性(非参数或返回值的const属性)不同的重载。例如:

    classTestConstReload
    {
    public:
        int& val()
    const
      
    {
            cout<<"const"<<endl;
            return const_cast<TestConstReload&>(*this).v;
        }

        int& val()
        {
            cout<<"non-const"<<endl;
            returnv;
        }

    private:
        intv;
    };

    成员函数具有const重载时,类的const对象将调用类的const版本成员函数,类的非const对象将调用非const版本成员函数。

    如果只有const成员函数,类的非const对象也可以调用const成员函数。                          ——这个思路来描述很囧。下同。

    如果只有非const成员函数,类的const对象…额,不能调用非const成员函数。                ——其实跟上一句的意思是一样的:const对象只能调用它的const成员函数。

    总的来说,就是当我们调用一个成员函数时,编译器会先检查函数是否有const重载,如果有,将根据对象的const属性来决定应该调用哪一个函数。如果没有const重载,只此一家,那当然就调用这一个了。这时编译器亦要检查函数是不是没有const属性而调用函数的对象又有const属性,若如此,亦无法通过编译。


    三、const属性的继承

    这里所说的继承与类层次的继承没有关系,意思是指:当我们定义一个const对象时,对象中的数据成员也将具有const属性(不论成员声明是否有const修饰)。这个很好理解,就好比一个const int,其中4个字符都不可更改一样,const对象中的所有数据也同样不可更改。但我之前没有意识到这一点,所以列在此。

    在上面的示例类型声明中,int& val() const 之所以要在最后去掉对象的const属性再返回,就是因为若不如此,则类const对象将无法调用此成员函数。

    int& val() const
        { 
            cout<<"const"<<endl;
            return const_cast<TestConstReload&>(*this).v;
        }
    
        const TestConstReload obj;
        obj.val();     //error : cannot convert from ‘const int’ to ‘int'

     

    四、const的编译期优化

    网上一篇文章描述了这样一个示例:

    int main()
    {
        const int a = 1;
        int *p = const_cast<int*>(&a);
        *p = 2;
        cout << “°value a=”± << a << endl;
        cout << “°value *p=”± << *p << endl;
        cout << “°address a=”± << &a << endl;
        cout << “°address p=”± << p << endl;
        return 0;
    }
    
    //输出
    value a=1
    value *p=2
    address a=0xbfe9efb4
    address p=0xbfe9efb4(depends on machine)

    文中同样有相关解释:即使在内存中某个地方存放了a对象,编译器也有可能在引用此变量的地方真的引用它。如果这个对象很小,并且它是常量,在编译时编译器就已经知道它的值。那编译器完全有可能在生成汇编的时候,用一个与它值相同的立即数来代替内存地址——这可以减少一次内存读取操作。原文在此:慎用const_cast


    五、托管C++中没有const成员函数

    如果在VC.NET中声明一个托管C++类,那么它的成员函数将不能应用const属性。我没有找到关于这一点的说明,大概是因为MISL方面的原因吧。如果哪位有关于托管C++中const的其它资料,请告诉我。




    题外话:
    1. 总结很费时,不过有助于理清知识和锻炼写作能力。 2. Live Writer怎么不好用了啊,郁闷。害我直接写HTML。哎,貌似很多大牛都是直接写HTML的...

  • 相关阅读:
    最大后验估计(MAP)
    mysql启动问题access denied for user 'root'@'localhost'(using password:YES)
    Median of Two Sorted Arrays-----LeetCode
    Two Sum-----LeetCode
    动态资源不缓存 filter
    过滤器 filter
    分页
    aop动态代理 事务 threadlocal
    ThreadLocal 开启事务
    数据库 元数据
  • 原文地址:https://www.cnblogs.com/yedaoq/p/2032597.html
Copyright © 2020-2023  润新知