郑辉的博客
百度首页 | 百度空间
 
文章列表
 
2008-08-22 18:54

这几天看到C++ Primer关于类和操作服重载的章节了。这本书给我一种感觉是越到后面讲的越快,内容都只是点到为止,总是感觉说的话背后还有话,但是不知道是什么,前 几天遇到的那个关于拷贝构造函数的问题书上相关的内容只有一句;今天又特迷茫操作符重载、类型转换、重载确定的问题,但关于这几个问题的描述分布在全书好 几个地方,而且也没有描述出一个原则性的东西,更要命的是看前面的部分的时候我都没有发现错误,今天竟然看到了一个错。我不怀疑书作者所说的权威性,但是 我怀疑他或者出版社有笔误……

按照计划,后天这本书就可以看完了,也可以写个评价了。现在我觉得这本书正如其名可以说是一个初级读 本,回想整本书,它很早因入了标准库的相关概念,在叙述完第一部分的时候,我觉得就把整本书的基调确定了:后面的章节在阐述前面遇到的概念和解决相关问题 的过程中把C++介绍给读者。可以说,这本书算是一个tutor,优点在于看完后能够知道C++相关的都有哪些概念,看它也可以很早就写出一些程序;但是 缺点是对一个概念的叙述过于分散、而且不便于深入,看完后很难形成对C++系统的理解。

这本书结束后,主要遗留的问题是:1、没有 形成用C++设计程序的思路;2、对类复制、操作符和函数重载及重载确定、类型转换等过程没有形成清晰概念;3、不了解库设施。但我没有太多时间了,必须 要开始学习算法了,尤其是数值算法,因此下面关于计算机技术的学习将由算法与数据结构、数值算法、C++程序设计语言、C++标准、Emacs五个部分交 替进行。另外再过三个星期就要开学了,这本书结束后我要把每天一半的精力放在我的课题上了,剩下的时间除了计算机,还要学英语。靠,时间真够紧张的……

 
2008-08-20 20:15

今天看到了C++ Primer中的复制、赋值、析构部分了,不知道为什么,看起来太迷茫了,而且上网上看看别人怎么说的,发现大家的理解都不一样,让我更加迷茫了。我又反反复复地读了读C++ Primer相关的章节,有了一点点自己的理解。


正如C++ Primer里面所讲,在


  • 根据另一个同类型的对象显式或隐式初始化一个对象。

  • 复制一个对象,将它作为实参传给一个函数。

  • 从函数返回时复制一个对象。

  • 初始化顺序容器中的元素。

  • 根据元素初始化式列表初始化数组元素。

这 些情况下将启用复制初始化过程:复制初始化首先使用指定构造函数创建一个临时对象(待复制的对象和目标对象类型相同,则没有该过程),然后用复制构造函数 将那个临时对象复制到正在创建的对象。复制初始化包含两个步骤说明了要区分“复制初始化”和“调用复制构造函数”这两个概念,复制初始化过程还可能调用直 接构造函数。以复制对象作为实参传递给一个函数为例:如果被调函数声明为:RT f(IT obj);调用语句为:f(obj_parm),而IT类可以以obj_parm为直接构造函数的参数,那么将在调用时发生如下过程:首先生成一个临时的 IT类型变量t_obj,然后调用直接构造函数初始化t_obj(隐式转换过程),然后调用复制构造函数以t_obj参数开辟形参内存空间并初始化。上面 两个过程我想也可以这么理解:第一步发生隐式类型转换生成一个临时变量,然后把该临时变量初始化给对象(哪一种理解才是正统???)。此外,C++ Primer里叙述了那么多启用复制初始化过程的情况,也说明了初始化时使用"="运算符只是复制初始化的一种,不是全部。

以 上这些是概念上的过程,我写程序在GCC4.2下验证,发现实际过程如下:使用直接构造函数直接开辟形参内存空间并初始化。这也就是说在GCC4.2实际 工作过程中,并没有调用复制构造函数。为了检验编译器到底需不需要复制构造函数,我又作了另外一个实验:把函数形参的类的复制构造函数放到private 访问标签下,结果编译出错。函数参数的调用过程还是应该在概念上理解为两个过程,并且存在一个临时对象,但实际上编译器优化了这两个过程,合而为一,只有 一次构造函数的调用,并优化掉了临时变量,只有实参类型和形参类型匹配时才会调用复制构造函数。


我还实验了书中所说的引发复制初始 化的其他过程,发现当需要类型转换时,只有顺序容器才会调用复制构造函数。那么复制构造函数的意义在什么地方?我能想到的首先一个地方就是将复制构造函数 放入private访问标签下防止对象复制;其次是控制复制过程,但我还对C++以这种方式控制初始化的合理性表示怀疑。我想完全可以用不定义参数为同类 型引用的构造函数防止复制,定义函数体为空的复制构造函数说明采用合成复制构造函数,定义不空的函数来控制复制过程;这种方式看起来也更自然一些,不知道 是C++标准制定者有什么特殊的考虑,还是我理解还不到位。


还有一个问题困惑过我一段时间:使用"="调用复制初始化函数和使用重 载赋值运算符"="有什么区别。还句话说,在形式上看,两者的参数一致,“返回值”(认为复制构造函数返回该类型的引用)也一致,作用也似乎一致,为什么 函数体往往有那么大的区别?这个问题现在的理解是:使用"="复制初始化的过程中除了调用复制构造函数、可能的直接构造函数调用之外还有一个为对象开辟内 存空间的过程,而赋值运算符被使用时,左操作数的内存空间必须存在;这个差别就意味着写赋值运算符"="函数体的时候不仅要考虑如何构造对象,可能还需要 考虑左操作数的析构问题;而调用复制构造函数的过程中不需要考虑析构。


关于如何理解复制初始化、复制构造函数、赋值运算符这些概念的这个问题还没有完,总感觉特别别扭,准备先把书看完,这个问题以后还要解决。


==========新的一天===========


今 天bbs上牛人作答了:标准规定了语义上的确是先用直接构造函数建立一个临时对象,然后调用复制构造函数把临时对象拷贝到正在建立的对象上,但标准允许实 现省略复制拷贝函数(即使复制拷贝函数有副作用)。需要注意的是,GCC编译器仍然会检查标准规定的语义,如果复制构造函数为private时,GCC就 会报错;这点和VC不同,VC不检查该语义,直接省略了复制构造函数。


但又有一个新问题,T obj2 = obj1的实现过程我仍然有疑问:是按照两步的开辟obj2的空间,然后调用复制构造函数把obj1复制到obj2上,还是说先建立一个临时对象 t_obj,然后调用复制构造函数复制obj2到t_obj上,然后更名t_obj为obj2?我觉得t_obj完全可以不要,但bbs上的牛人为什么特 别说有t_obj???

==========新的一天===========
原来我一直不明白exciplit关键字的含义,今天看了楼下哥们的文章之后有了这么的理解:当构造函数声明为exciplit时,该构造函数只能通过调用操作符的形式调用,而没有该关键字时,构造函数的调用可以通过=操作符、return语句、实参到形参等方式完成。

此问题仍未结束……

==========我是分割符===========

本想给楼下的兄弟一个回复,结果回复太长了,被百度给截断了,于是写在这里:

我的困惑主要集中在类似于函数返回对象的内存分配和初始化是否同时完成这类问题上。
例如:

class A;
A func(void) {
return A(); // line 1
}
int main(void) {
func(/*null*/); // line 2
return EXIT_SUCCESS;
}
上面line2处的函数调用表达式将会产生一个对象(暂时命名为obj2)作为表达式的值,但问题是该对象的内存分配和对象的初始化都是在什么时间完成的。我想有两种可能的过程:
  1. 在 主函数中执行到func()调用的时候,编译器根据func的声明分配一篇内存空间(这个就是obj2)作为将来存放调用表达式值的空间,然后开始调用函 数func()。当在func()中,执行到return时,先使用直接构造函数产生对象obj1,然后return语句调用复制构造函数把obj1复制 初始化到obj2,而obj1将被销毁。也就是说obj2内存开辟和初始化并不是相连发生的。

  2. 在主函数中执行到line2时, 编译器知道表达式应该有一个名叫 obj2的对象作为表达式的值,但是它并不在此时开辟内存空间,而是先调用func()。在func()中执行到line1时,直接构造函数A()的调用 将产生一个对象obj1,然后编译器再开辟一片临时内存空间t_obj,调用复制构造函数把obj1复制初始化到t_obj。最后func()调用结 束,return语句将把t_obj更名为obj2,然后obj1被销毁。

上面两种过程都有一些问题:如果是 第一种过程,假如在func()中出现了异常而导致func没有执行return语句,就会导致在主程序中obj2对象没有初始化,以后主程序中任何使用 obj2对象的地方(除了赋值)都可能导致错误;如果是第二种过程,main()函数作用域中的ojb2对象的内存分配过程是在fun()函数作用域中完 成的,也就是说非动态对象的生命周期并不与作用域相同,不知道这是不是合理的。

 
2008-08-14 03:25

一直以来感觉unix-center上的bash只显示bash和版本号,非常不爽,今天才知道可以修改PS1的值来改变bash显示信息。我把它修改成PS1='\u@\h:\w\$'来显示"用户名@主机名:完整目录名$(当为root时为#)"这样的信息。
其他可用的扩展:


转义字符 描述
\t \t 是时间,显示格式为HH:MM:SS
\d \d 是日期,格式为“工作日名称 月份 日期”(例如,星期五 10 月 13 日)。
\n \n 是换行。
\s \s 是 Shell 名称(通常为 bash,如果该 Shell 是登录 Shell,则为 '-bash')。
\v \v 是bash版本号,如3.00。
\w \w 是当前目录的完整路径。
\W \W 是当前目录的最后一部分(换句话说,就是 '/home/mc' 中的 'mc')。
\u \u 是您的用户名。
\h \h 是主机名。
\# \# 是此命令的命令编号(该值在每行递增)。
\! \! 是此命令的唯一历史记录编号。
\n n \nnn 是由八进制 nnn 所标识的字符。
\$ \$ 在有效 UID 为零时为 # 字符,否则为 $ 字符。
\\ \\ 是反斜杠。
\[ \[ 开始一个转义序列;一般用于颜色设置和标题的终端控制字符。
\] \] 结束转义序列。

 
2008-08-13 00:14

除了前一篇文章说的问题之外,今天我又在字符串常量上遇到了一个问题:



  1. char *pc = "Hello World"; // (1)正确

  2. const char *cpc = "Hello World"; // (2)正确
    char *pc = cpc; // (3)错误

C++ 中不允许将指向const对象的指针赋于指向非const对象的指针,所以(3)是错误的。而字符串常量隐式转换为const char*型指针,所以赋予const char*指针是没有问题的,(2)是正确的。但是第一行把字符串常量赋予char *指针也是正确的,查看标准(标准4.2节和Annex D.4),发现这是允许、但“deprecate”(不推荐)的,也算是C++中的一个特例吧。

 
2008-08-10 10:20
今天刚注意到,发文庆祝一下。
 
2008-08-09 15:00

关键字:CPP 指向const对象的指针 const指针 字符串常量

今天看到C++ Primer数组和指针了。看完后想到一个问题,不明白:C++中字符串常量当作const char型的数组,但是为什么下面两段代码是正确的?



  1. const char *pc = "Hello World!"; // 定义

  2. const char *pc;
    pc = "Hello World";

回 宿舍的路上想到对const变量赋值时,突然想明白为什么了:我对const char型数组理解错了。数组名隐式转换为指针,这里字符串常量本身就是它所代表内存对象的名字;const char修饰的是指针所指的内容有只读属性,而不是该指针保存的地址有只读属性。所以,这两个例子不是对const指针的初始化和赋值,而是对指向 const对象的指针的初始化和赋值,所以不能按照const变量的初始化和赋值的相关规则来理解。
归根到底,还是我对const指针和指向const对象的指针(const int * const pa;)的理解不到位。

 
2008-08-05 21:33

前几天,一些网站报道说,谷歌的蜘蛛机器人开始索引音乐,有人猜测是谷歌开始尝试音乐搜索。今天,谷歌正式宣布提供音乐搜索http://googlechinablog.com/2008/08/blog-post_6968.html。与百度采用独立一个域 名mp3.baidu.com专职搜索音乐不同,只要在谷歌搜索框中以歌手、专辑名、歌曲名为关键词搜索,就会在搜索结果的最上面一栏显示相关的图片、信 息、试听链接和下载链接。另外一点和百度不同的是,百度音乐搜索的链接“来源广泛”,很多是没有版权的;而谷歌通过与巨鲸合作的方式,提供巨鲸上正版音乐 资源的试听和下载。


一个星期之前,我和女朋友一起在地坛玩的时候聊到百度的音乐搜索。当时我说,我最欣赏百度的两个产品,音乐搜索 是其中一个。我还说到了北大的maze系统:不提版权问题、色情资料泛滥和差劲的搜索能力,我挺喜欢maze系统,因为它提供了以用户为中心的资源整合方 式。每个用户的maze共享里面的资源都是自己辛苦搜集来的,反映了这个用户的兴趣。我经常发现,我如果有某个下载需求,总是有用户提供了非常系统的资 源。例如,我想看最近的某一部电视剧,我经常能非常惊喜地发现某个用户的maze中里搜集了这部电视剧的每一集,然后咱就好不客气地全部下载下来;还有一 段时间,我想完整的听完一个专辑,然后我又很惊喜的发现,有些人已经替我搜集好了,专辑里面所有的歌、歌词和介绍都有了;另外,有些用户按照适合播放的环 境搜集音乐,我经常可以在maze中看到什么适合睡觉前听、适合学习时听、适合心情不好时听的多少多少首歌这样标题的文件夹,然后也毫不客气全部下载下 来;最后maze的级别系统虽然很粗糙,但是我的确发现级别高的用户的资源的确是比级别低的用户搜集的资源更好。我想百度的音乐盒、掌门人对音乐的整合作 用和maze系统对资源的整合作用非常类似,它们都提供了一种由用户来搜集和整理资源的途径,而且我觉得最后给用户带来了的体验也将是类似的。


除 了上面这些,我还想说说maze系统包括百度的音乐搜索、音乐盒、掌门人不太另外满意的地方。在maze中,大部分用户的文件夹里面资源乱七八糟,这些资 源在整合性上太差了,但是如果用户只希望得到一个资源,而使用搜索的时候,maze应该能够找到这些资源,但可惜的是,maze的搜索太弱了,经常找不到 资源,逼迫我一个一个翻别人的共享文件夹。另外,maze提供了分级制度、资源屏蔽制度、好友和黑名单制度来控制资源质量,尤其是分级制度。一般用户等级 高,资源质量也相对较好,但这是有很多例外的。我想作为著名搜索引擎的百度,在资源定位和资源分级上具有自己得天独厚的优势,应该能做的更好,但实际上我 还需要在百度搜索结果上翻好几页才能找到能用的、我满意的资源。另外,虽然百度掌门人提供了一种依据歌手划分资源的方式,但是如果我想得到某个专辑的详细 信息,比如说是在歌手什么状态下创作的、有什么背景、甚至专辑发布的日期、销售量都是比较困难的,而这一点完全可以通过和百度空间、贴吧、百科的整合,依 靠大量的粉丝完成。


但百度音乐最大的问题是版权问题,我想可以说是百度音乐搜索伴随着并推动着中国盗版音乐的蓬勃发展,即便百度打 赢了官司,但我认为百度也要对中国盗版音乐发展负有不可推卸的责任,而这不是一个有社会责任感的企业应该做的。盗版音乐的猖獗无疑严重打击中国音乐的发 展。我曾经试想通过发行商提供在线免费试听并提供广告,加上下载付费的方式,来期望得到一种既保护了版权所有者的利益,又方便用户的一种方式(随便说一 句,这还需要通过国家立法打击想百度这样的提供盗版资源的搜索提供商,以及开发更先进的技术手段防止出现像1ting那样试听变下载的情况等多种手段来实 现)。今天,谷歌推出了音乐搜索,我欣赏谷歌音乐搜索对版权问题的处理,和我预想不同的是,它的下载也是免费的,收入只靠广告分成,而没有下载付费这样的 收入渠道。能不能成功,我们拭目以待,但我想,虽然谷歌在单一资源的机器定位、分级方面比百度强,但它比起百度差距最大的一点是:谷歌没有合适的、以用户 为主的资源整合平台。有时候我在想,这点在有些方面尤其在音乐搜索方面是谷歌致命的缺陷,毕竟,我们找音乐资源不仅仅需要单一歌曲的精确定位,还需要对资 源的整合、通过一次搜索得到许多相关资源的方式。或许,这个音乐搜索能让谷歌发现自己在用户为中心资源整合上的缺陷,努力发展相关的平台;也有一种可能音 乐搜索失败,使谷歌认识到自己和百度在搜索哲学上的不同,谷歌和百度出现分化,分庭抗争。


一家之言。

原文:huizheng.blogspot.com

 
2008-08-01 19:42

www.eclipse2008.cn上的信息:08年8月1日下午6点59分,北京地区可以看到日偏食。我和魏玉科兴匆匆地跑到静园草坪,结果只看到了西山上空美丽的云;而太阳只在日食前从云里探了个头,之后就躲后面了。本世纪我的第一次观日食的行动就这么遗憾的结束了……

奥运日食日,北京两起自杀,而更难受的是,其中一起发生在离我不到50米的地方。我看到消息和图片的时候,心里格外的别扭。
珍爱生命,树立远大的目标,远离自杀。

 
2008-08-01 17:13
每天关注的事情不能超过三件。一段时间内,精力集中在一件事情上,不能来回摇摆。
 
2008-07-31 18:00

标题档。

QQ for linux主页:http://im.qq.com/qq/linux/

 
     
 
 
个人档案
 
zhenghui1988

北京 海淀区 
上次登录:
50分钟前
加为好友
 
   
 
日历
 
     
 
文章分类
 
 
 
 
Vim(1)
 
 
 
 
Cpp(4)
 
Bash(1)
 
     
 
留言板
 
     
 
最新评论
   
     
 
好友最新文章
 
     
 
最近访客
 
 

myzjdx

galoispure

liusong_hi

东方名猪2008

eabesqxt

樱星璇

alice_xc

历史的前沿
     
 
其它
 
已有人次访问本空间
 
订阅RSS  什么是RSS?

您也想拥有这样的空间?请点此申请。
     


©2008 Baidu