24小时热门版块排行榜    

查看: 1383  |  回复: 14

huycwork

金虫 (著名写手)

【答案】应助回帖

★ ★
余泽成(金币+2): 鼓励交流! 2011-06-08 16:14:19
呃,我好像没有回答楼主的问题呃,再补上。
正常情况下,返回一个对象需要调用一次复制构造函数将返回对象保存到一个安全的地方,然后删除栈对象,等到函数返回之后,再对保存好的对象操作。因此,这里必须有一次复制构造。
但是楼主困惑的这个问题并不是由复制构造函数引起的,而是由f()和g()这样的短函数引起的。C++有一个inline的特性,它阻止任何浪费时间的函数调用,inline关键字对编译器只能是建议,这无法直接控制。从结果来看,这里没有复制操作,实际上就是没有函数调用,换句话说,就是内联展开了。
漩涡的中心有一块空地,空空的。
11楼2011-06-08 12:40:49
已阅   回复此楼   关注TA 给TA发消息 送TA红花 TA的回帖

来自天狼

木虫 (正式写手)

★ ★ ★
微尘、梦想(金币+3): 鼓励交流!辛苦了…… 2011-06-20 19:42:37
看了楼主的问题,才知道自己的C++功底不扎实,为了搞明白这个问题,这几天真是寝食难安。查了所有能找到的C++书,还在网上扒了无数网页,加上自己的思考,终于有所收获,虽然已经结贴,但还是想谈谈自己的看法。
    我用的是vs2005,如果在“项目”->“属性”->“配置属性”->“C/C++”中把“优化”禁用(原设置是“完全优化(/0x)”),把main函数中的代码全部屏蔽,只写一个g();则输出为“调用复制构造函数”。用point p3 = g();测试,只输出一行“调用复制构造函数”,这说明g()返回时调用了复制构造函数,这一点容易理解,但是赋值给p3时并没有调用,这一点就不好理解了。
    C++中设置复制构造函数的目的,主要是为了解决用一个对象给另一个对象赋值时的深拷贝问题。楼主的例子中没有用到深拷贝,我们可以假设其中存在深拷贝,不论g()中定义的对象q有没有分配资源,在return时都会调用复制构造函数把q复制到一个临时对象中,临时对象中的资源会重新分配。以point p3 = g();为例,如果=操作符也调用复制构造函数的话,那么这一个语句中就会有三次分配资源的行为,g()中定义的q一次,return给临时对象时一次,把临时对象复制到p3时又一次,如果资源比较大的话,效率会非常低。如果我是编译器的设计者,一定会想办法提高效率,因为临时对象只起到了一个中转的作用,完全没有必要,所以可以直接把g()返回的临时对象返回到p3中。
    为彻底搞清楚编译器都做了什么,只好祭出反汇编大法,单步跟踪point p3 = g();逐条指令硬啃,证明编译器确实只调用了一次复制构造函数,而且是直接把g()的返回值返回到了p3中。单独一个g();也会调用复制构造函数,只不过是把结果返回到栈上的无名空间(对象)中。
    未优化的代码中,point p5 = p3; 的反汇编码跟 point p2(p1); 的反汇编码一模一样。可见编译器是把 point p5 = p3; 当成 point p5(p3); 来处理的。
    以上是禁用优化的情况,如果配置为“完全优化”,那么本例中的point p3 = g();是不会调用复制构造函数的。因为g()只有两条语句,而且没有分配资源,被编译器直接内联了,反汇编码中是直接把g()中定义的q(3,5)赋值给p3的。

    在VC6.0中,同样的代码point p3 = g();在未优化的情况下,会输出两个“调用复制构造函数”,可见不同的编译器对复制构造函数的处理是不同的。

    根据这几天在解决问题过程中的摸索和思考,认识到C++标准虽然定义了许多规范,但是编译器在实现时并没有拘泥于这些条条框框。更是认识到实践是检验真理的唯一标准,尽信书则不如无书。

    以下是两个参考的网页:
复制初始化、复制构造函数、赋值运算符
http://hi.baidu.com/zhenghui1988 ... 3ce020cefca305.html
    标准规定了语义上的确是先用直接构造函数建立一个临时对象,然后调用复制构造函数把临时对象拷贝到正在建立的对象上,但标准允许实 现省略复制拷贝函数(即使复制拷贝函数有副作用)。需要注意的是,GCC编译器仍然会检查标准规定的语义,如果复制构造函数为private时,GCC就 会报错;这点和VC不同,VC不检查该语义,直接省略了复制构造函数。

构造函数,默认构造函数,复制构造函数,赋值构造函数
http://zjayang198861.blog.163.co ... romSearchEngine=yes
12楼2011-06-20 16:28:15
已阅   回复此楼   关注TA 给TA发消息 送TA红花 TA的回帖

huycwork

金虫 (著名写手)

引用回帖:
Originally posted by 来自天狼 at 2011-06-20 16:28:15:
看了楼主的问题,才知道自己的C++功底不扎实,为了搞明白这个问题,这几天真是寝食难安。查了所有能找到的C++书,还在网上扒了无数网页,加上自己的思考,终于有所收获,虽然已经结贴,但还是想谈谈自己的看法。
...

OrzOrzOrz...
天神下凡,文曲在世啊,再次膜拜~Osz~
漩涡的中心有一块空地,空空的。
13楼2011-06-20 17:14:41
已阅   回复此楼   关注TA 给TA发消息 送TA红花 TA的回帖

文俊点点

木虫 (著名写手)

★ ★
微尘、梦想(金币+2): 鼓励交流! 2011-06-20 19:43:00
有如此神奇之高人,还是学金融的,让科班出身之人蒙羞啊········
另外提一点,楼主的基本定义把握不是很准,要按照书上什么复制,重载之类的向上推会越来越麻烦,就是最基本的,没有的才初始化,有了就不用初始化。
这是你所拥有的时间·····这是你所能改变的生活·········
14楼2011-06-20 18:17:12
已阅   回复此楼   关注TA 给TA发消息 送TA红花 TA的回帖

sudo

木虫 (正式写手)

★ ★ ★
微尘、梦想(金币+3): 鼓励交流! 2011-06-20 19:43:12
引用回帖:
Originally posted by 来自天狼 at 2011-06-20 16:28:15:
看了楼主的问题,才知道自己的C++功底不扎实,为了搞明白这个问题,这几天真是寝食难安。查了所有能找到的C++书,还在网上扒了无数网页,加上自己的思考,终于有所收获,虽然已经结贴,但还是想谈谈自己的看法。
...

来唱个反调

我感觉标准其实不是条条框框,而是对于一个问题,大家的实现方式不一样,然后发现这样会给后来人带来困扰,于是标准才出现了

当然c++的新标准也才出来不久,还没来得及阅读,虽然其中可能有一些有争议的东西,但是,总体来说不能否定标准存在的价值。(咳虽然C++的标准不像C标准那么深入人心)

VC6很老的东西了,很多c++特性都不支持(C++ Primer上的好多例子在VC6上是有问题的,好像说当年标准没定,也难怪。不过这些东西在今天看来是司空见惯了),用它的行为反过来来解释标准,有点偏颇了

对编译器而言,完全遵循标准似乎还没哪个做得到。但是,倒是没有哪个编译器因为不遵守标准还理直气壮的......嘛,新的c++标准争议还挺多,姑且不论,下一代编译器也还没出来...
15楼2011-06-20 18:39:15
已阅   回复此楼   关注TA 给TA发消息 送TA红花 TA的回帖
相关版块跳转 我要订阅楼主 微尘、梦想 的主题更新
信息提示
请填处理意见