免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
12
最近访问板块 发新帖
楼主: changkaizhao
打印 上一主题 下一主题

[C++] 这个是怎么回事? 新手求解~~~ [复制链接]

论坛徽章:
24
金牛座
日期:2013-08-21 07:55:52射手座
日期:2014-09-29 15:36:14摩羯座
日期:2014-10-07 21:42:57天秤座
日期:2014-10-16 10:03:00午马
日期:2014-10-19 13:40:31酉鸡
日期:2014-11-08 08:44:54处女座
日期:2014-11-10 17:01:21午马
日期:2014-12-06 16:52:38羊年新春福章
日期:2015-02-12 17:41:512015年迎新春徽章
日期:2015-03-04 09:58:1115-16赛季CBA联赛之广夏
日期:2022-10-07 19:41:11巳蛇
日期:2014-09-13 15:29:54
11 [报告]
发表于 2014-11-02 18:07 |只看该作者
回复 9# shan_ghost
好人, 要学习的还有好多

   

论坛徽章:
0
12 [报告]
发表于 2014-11-02 18:18 |只看该作者
本帖最后由 changkaizhao 于 2014-11-02 18:22 编辑

回复 9# shan_ghost

首先非常感谢你细心的回答。

1.   对于你提到的第2条:   如果  delete p;   p = nullptr;  后原来指向的堆的内存会释放吗?

2.   对于第3条, 我确实 在基本的程序 编译和运行过程中的一些内存概念比较模糊。 能否推荐几本非常好的 C++书 能够详细讲解程序编译和运行过程中 内存的管理机制。
     
3.   对于 第4条,类信息是全局唯一的,所以怎么调用类的公共成员函数都没问题。 为什么会这样?类信息表 是什么东西? 我一直以为只有实例化对象(A *p = new A(); 这种方式也算实例化对象吗?)后才能调用类函数。  对于编译器 而言 p -> helloworld();  如下,

__A__helloworld(p);

void __A__helloworld(A* this)
{
    printf("hello world");
}

__A__helloworld();

这些再程序编译后就是这样的东西。  
所以我用下面语句也可能得到 结果。
    ((A*)&std::cin)->helloworld();

论坛徽章:
0
13 [报告]
发表于 2014-11-02 18:23 |只看该作者
回复 10# folklore


    成员函数保存在哪里?

论坛徽章:
8
CU大牛徽章
日期:2013-04-17 10:59:39CU大牛徽章
日期:2013-04-17 11:01:45CU大牛徽章
日期:2013-04-17 11:02:15CU大牛徽章
日期:2013-04-17 11:02:36CU大牛徽章
日期:2013-04-17 11:02:58技术图书徽章
日期:2013-12-04 10:48:50酉鸡
日期:2014-01-03 10:32:30辰龙
日期:2014-03-06 15:04:07
14 [报告]
发表于 2014-11-04 12:44 |只看该作者
回复 12# changkaizhao


  
1.   对于你提到的第2条:   如果  delete p;   p = nullptr;  后原来指向的堆的内存会释放吗?


会。执行delete时已经释放。


2.   对于第3条, 我确实 在基本的程序 编译和运行过程中的一些内存概念比较模糊。 能否推荐几本非常好的 C++书 能够详细讲解程序编译和运行过程中 内存的管理机制。

建议先看c++ prime之类书籍,并尽量多做练习,把指针彻底搞懂。


然后,如果有兴趣的话,可以看微机原理、操作系统原理,以及可执行文件的格式、载入及执行机制等方面的知识。

这是因为,c/c++虽然几乎一刻都离不开内存管理;但这门语言只是通过malloc/free和new/delete在申请、归还内存而已,并未深入细节,也不需要深入细节(所以c/c++相关标准根本就不提堆这回事)。



3.   对于 第4条,类信息是全局唯一的,所以怎么调用类的公共成员函数都没问题。 为什么会这样?类信息表 是什么东西? 我一直以为只有实例化对象(A *p = new A(); 这种方式也算实例化对象吗?)后才能调用类函数。  对于编译器 而言 p -> helloworld();  如下,

__A__helloworld(p);

void __A__helloworld(A* this)
{
    printf("hello world");
}

__A__helloworld();

这些再程序编译后就是这样的东西。  
所以我用下面语句也可能得到 结果。
    ((A*)&std::cin)->helloworld();



简单说,类内部函数会被按一定格式重命名(如 classA::func1_void_void),编译后存储于一个叫代码段的特殊位置(现代操作系统中,只有这个段的内容才是可执行的)。

然后,调用这个函数,就是用一条call指令跳到代码段的对应位置执行,执行完成后,通过一条ret指令返回当初的call指令的下一条指令位置继续执行(call指令执行时,会把自己的位置压入栈中)。


换句话说,类成员函数与类绑定,并不会为每个对象存储一份(否则要多浪费多少空间)。


这个绑定信息(包括有哪些成员函数、成员变量、虚函数入口表内容等信息),则会放到一个全局的、以class名称(实际可能是class id)索引的数据结构中去。



而classA实例化的对象A,则可能是这个格式:
A ----> {
   vptr;            //指向虚函数入口表,有虚函数才会有这个

   int i;            //你定义的成员变量
}



这些对象布局的知识,在比较靠谱的c++教材中是应该提到的。

论坛徽章:
0
15 [报告]
发表于 2014-11-09 22:39 |只看该作者
回复 14# shan_ghost


    多谢 大神指点,受益匪浅~~~
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP