惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

T
Tor Project blog
博客园 - 聂微东
Microsoft Azure Blog
Microsoft Azure Blog
博客园 - 【当耐特】
G
Google Developers Blog
J
Java Code Geeks
The Cloudflare Blog
Attack and Defense Labs
Attack and Defense Labs
宝玉的分享
宝玉的分享
Last Week in AI
Last Week in AI
Cisco Talos Blog
Cisco Talos Blog
酷 壳 – CoolShell
酷 壳 – CoolShell
I
Intezer
Jina AI
Jina AI
T
Tenable Blog
P
Palo Alto Networks Blog
Project Zero
Project Zero
D
DataBreaches.Net
Hugging Face - Blog
Hugging Face - Blog
The Hacker News
The Hacker News
F
Full Disclosure
Cloudbric
Cloudbric
量子位
H
Heimdal Security Blog
K
Kaspersky official blog
有赞技术团队
有赞技术团队
罗磊的独立博客
V
Vulnerabilities – Threatpost
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
阮一峰的网络日志
阮一峰的网络日志
Vercel News
Vercel News
Recent Announcements
Recent Announcements
WordPress大学
WordPress大学
GbyAI
GbyAI
S
SegmentFault 最新的问题
M
MIT News - Artificial intelligence
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
I
InfoQ
Recorded Future
Recorded Future
Security Archives - TechRepublic
Security Archives - TechRepublic
AI
AI
Webroot Blog
Webroot Blog
C
CXSECURITY Database RSS Feed - CXSecurity.com
爱范儿
爱范儿
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
T
The Exploit Database - CXSecurity.com
Apple Machine Learning Research
Apple Machine Learning Research
C
Cybersecurity and Infrastructure Security Agency CISA
H
Hacker News: Front Page
Latest news
Latest news

博客园 - 泉子

算法题:求一个序列S中所有包含T的子序列(distinct sub sequence) Django模板输出Dict所有Value的效率问题 笔记:LNK2001不代表链接器真的需要链接相关符号 Windows Restart Manager 重启管理器 advapi32.dll kernel32.dll 中的两套注册表API 使用GDI+保存带Alpha通道的图像(续) 使用GDI+保存带Alpha通道的图像 窗口销毁的相关函数与消息,ActiveX控件的销毁 为什么不能将ptr_fun(operator delete)传递给For_Each 两个数之间的最短路径问题 C/C++函数中局部对象的构造与析构时机 四年记——身在中小企业 [转载]怎样用VB编写.DLL动态链接库文件 Visual Studio 6.0编译PWLib1.12总结 在Windows上编译PWLib 金山词霸没落了么? SendInput模拟键盘输入的问题 数组变量在取地址时回归:不再是指针 创建用于非Visual C++工具的DLL——VB调用C++ DLL为何必须使用def文件 - 泉子
C++ Const总结
泉子 · 2011-04-29 · via 博客园 - 泉子

一、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的...