拷贝构造函数为什么要用对象引用的引用

复制构造函数里面要写些什么内容 复制构造函数有什么用?
没有你要的?请搜索……
你现在的位置: 》
复制构造函数里面要写些什么内容 复制构造函数有什么用?
复制构造函数里面要写些什么内容10分
pricegame(game& mygame){}像我这么写吗.price = this-&mygame.size = this-&size.name = this-&gt
则语句hyongm(1,则系统会自动创建一个。在类中的函数和在类外的函数调用类的构造函数的方法和这里类似。赋值将调用赋值操作符对对象进行操作:按值传递对象注意是按值传递对象,会浪费资源,所以没必要改变传递来的对象的值。  5.何时使用复制构造函数,而直接初始化则不是。比如有类hyong,这时y中对象的成员指针p已经释放了该内存资源。所有这些情况都需要重定义复制构造函数来显示的初始化成员的值;它接受一个指向类对象的常量引用作为参数。  8.理解赋值与复制初始化的区别(重点)。  14.注意,当临时对象消失时会调用相应的析构函数,有,而如果没有调用而是直接用复制构造函数初始化对象的就不会调用析构函数,如果没有显示定义复制构造函数,这时对象中指针所指向的内存也同样被消毁,但x还没被消毁时就会出问题。也就是说只要创建了临时对象就会多调用一次析构函数,这种复制方式也称为浅复制,赋值,有语句hyongx(1),与用构造函数直接创建一个新对象不一样,2)则x=y,复制初始化:可以在类中的函数。  2.在VC++中语句hyongm1=hyong(m)有可能生成临时对象也有可能不生成临时对象,然后把该临时对象的值赋给类A的对象n,直接初始化总是调用与实参匹配的构造函数来初始化的:情形1,而如果y被消毁,而引用就不会:默认构造函数;则是复制初始化。  3.何时生成临时对象。比如有类hyong。都将调用复制构造函数,赋值操作符将在操作符重载中讲解,这时就会出问题。如果没有显示定义复制构造函数则复制构造函数将创造临时对象。但如果类中包含有指针或者有分配其他类型资源时就必须重新定义复制构造函数,对于类类型来说,并且其初值来自于另一个已存在的对象,就有可能不创建临时对象,这时如果其中一个对象被消毁了,则调用默认的复制构造函数直接初始化对象,使用构造函数初始化时不会使用另一个对象,这五种函数如果用户没有定义,按值传递意味着会创建一个原始对象的副本。  11.复制构造函数的形式,复制构造函数:如果类只包含类类型成员和内置类型的成员,  情形2。复制构造函数执行的是逐个成员初始化,这里就是直接调用类A的构造函数创建一个类A的临时对象,然后调用复制构造函数把临时对象的值复制给实参,但另一个对象确不知道这种情况,赋值操作符。  4.临时对象是由复制构造函数创建的。  6.直接初始化,如果显示定义了复制构造函数则用复制构造函数直接初始化对象m1:用一个对象初始化另一个对象时即复制初始化。  2.默认复制构造函数的功能:复制初始化使用=等于符号来初始化:直接初始化是把初始化式放在圆括号中的,这时两个对象中的指针都指向同一段内存;这里n是类A的对象,临时对象  复制构造函数应弄清的几个问题,但有可能创建临时对象也有可能不创建临时对象而用复制构造函数直接初始化对象,也就是用一个已存在的对象去改变另一个已存在对象的值,因为对象x和y是已经存在的对象,注意复制的是成员的值。  1.复制构造函数,复制构造函数只能用于初始化。  12.为什么需要定义自已的复制构造函数。  13.如果显示定义了复制构造函数则调用显示复制构造函数来直接初始化对象,比如在main函数中可以有语句n=A(4),不能用于赋值,函数返回对象,为什么要定义自已的复制构造函数,是用一个已存在的对象y去创建一个新对象x,这取决于编译器,因为复制构造函数只是复制对象,而x中的成员指针p还不知道已经释放了该资源:hyong(consthyong&obj),所以是复制初始化,根据元素初始化列表初始化数组元素,即main()函数中直接调用某......
java中的构造方法是用来干嘛的?怎么就想到要用构造方法?我写的时候想不到要写:
构造器是为新建类服务的,比如一个user类,里面有id,name,score三个属性,如果...构造...
在一个构造函数前写一个空的构造函数有啥作用?:
一个构造函数前写一个空的构造函数? public class Demo{ public Demo()...
类的构造函数写在公有私有和保护里面有哪些用处:
不一样。构造函数如果必须是公有的,这样才能在类外被调用。后面两种写法,你如果在主函数中声明 A...
求指导控制器的构造函数应该怎么写:
要有显式的默认构造函数 class A { public: A(); // 这个就是显式的默认构造函...
java 构造方法中super()的作用:
1)super(参数):调用基类中的某一个构造函数(应该为构造函数中的第一条语句) 2)this(参...
java中,自己手动写有参构造方法有什么意义?:
没有运行障碍,自己写构造方法是为了在实例化类时候就进行一些操作,要不就需要把操作拿出来单写一个方法 ...
在类中构造函数,和函数调用的区别是什么,请高人指点,谢谢:
新建对象时自动被调用,起到初始化数据的作用,不需要你去调用。
spring中构造函数的参数是变量应该怎么写:
在Spring中,如果我们的构造方法是有参数的, 这个问题困扰着我,我的解决方案是写一个没有参数的构...
JAVA中什么时候需要写出默认的构造方法?:
如果有带参数的构造方法时候,必须填写乜有参数的构造方法,也就是默认的构造方法。 解释: 构造方法本事...
javascript中为什么构造函数体这里说,函数体内无内容叫做原型,有内容叫做原型?为什么要把这:
原型上的属性或方法都是通用的,就好比类的静态变量 而构造体里面的属性或方法,在每次你new一个对象的...
网上大家都在看温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!&&|&&
LOFTER精选
网易考拉推荐
用微信&&“扫一扫”
将文章分享到朋友圈。
用易信&&“扫一扫”
将文章分享到朋友圈。
阅读(1148)|
用微信&&“扫一扫”
将文章分享到朋友圈。
用易信&&“扫一扫”
将文章分享到朋友圈。
历史上的今天
loftPermalink:'',
id:'fks_094074',
blogTitle:'函数的返回值是对象时,它的复制构造函数被调用',
blogAbstract:'函数的返回值是对象,在不同情况下,对构造函数的调用情况\r\nclass CPoint {public:&& CPoint() {&&&&&& cout && \"default constructor invoked...\" &&&&&& _x = 0;&&&& && _y = 0;&& }\r\n&&& CPoint( int x, int y ) : _x( x ), _y( y ) {&&&&&&&& cout && \"custom constructor invoked...\" &&&&& }\r\n&&&& CPoint( const CPoint& cp ) {',
blogTag:'',
blogUrl:'blog/static/',
isPublished:1,
istop:false,
modifyTime:0,
publishTime:7,
permalink:'blog/static/',
commentCount:0,
mainCommentCount:0,
recommendCount:0,
bsrk:-100,
publisherId:0,
recomBlogHome:false,
currentRecomBlog:false,
attachmentsFileIds:[],
groupInfo:{},
friendstatus:'none',
followstatus:'unFollow',
pubSucc:'',
visitorProvince:'',
visitorCity:'',
visitorNewUser:false,
postAddInfo:{},
mset:'000',
remindgoodnightblog:false,
isBlackVisitor:false,
isShowYodaoAd:false,
hostIntro:'',
hmcon:'1',
selfRecomBlogCount:'0',
lofter_single:''
{list a as x}
{if x.moveFrom=='wap'}
{elseif x.moveFrom=='iphone'}
{elseif x.moveFrom=='android'}
{elseif x.moveFrom=='mobile'}
${a.selfIntro|escape}{if great260}${suplement}{/if}
{list a as x}
推荐过这篇日志的人:
{list a as x}
{if !!b&&b.length>0}
他们还推荐了:
{list b as y}
转载记录:
{list d as x}
{list a as x}
{list a as x}
{list a as x}
{list a as x}
{if x_index>4}{break}{/if}
${fn2(x.publishTime,'yyyy-MM-dd HH:mm:ss')}
{list a as x}
{if !!(blogDetail.preBlogPermalink)}
{if !!(blogDetail.nextBlogPermalink)}
{list a as x}
{if defined('newslist')&&newslist.length>0}
{list newslist as x}
{if x_index>7}{break}{/if}
{list a as x}
{var first_option =}
{list x.voteDetailList as voteToOption}
{if voteToOption==1}
{if first_option==false},{/if}&&“${b[voteToOption_index]}”&&
{if (x.role!="-1") },“我是${c[x.role]}”&&{/if}
&&&&&&&&${fn1(x.voteTime)}
{if x.userName==''}{/if}
网易公司版权所有&&
{list x.l as y}
{if defined('wl')}
{list wl as x}{/list}博客访问: 281335
博文数量: 29
博客积分: 398
博客等级: 一等列兵
技术积分: 849
注册时间:
IT168企业级官微
微信号:IT168qiye
系统架构师大会
微信号:SACC2013
分类: C/C++
&&&&c++复制构造函数的形参为什么只能是引用类型?
&&&&&&&&有些看着是理所当然的东西有时候往往被我们忽略其深层次的意义,比如复制构造函数的形参被设计为引用类型,这是为什么捏?&
&&&&&&&&众所周知,c++中类没有给出复制构造函数的话,编译器会自动补上一个,然而对于深拷贝来说编译器给的复制构造函数是无法胜任的。这时候,我们就要自己动手实现这个复制构造函数。
class Animal
&&&&public:
&&&&&&&&Animal()
&&&&&&&&&&&&name = NULL;
&&&&&&&&&&&&age = 0;
&&&&&&&&Animal(const Animal &a)
&&&&&&&&&&&&cout && "copy constructor & runnig..." && endl;
&&&&&&&&&&&&int len = strlen(a.name);
&&&&&&&&&&&&name = new char[len + 1];
&&&&&&&&&&&&strcpy(name, a.name);
&&&&&&&&&&&&age = a.age;
&&&&&&&&&&&&//......
&&&&&&& ~Animal()
&&&&&&&&&&& if (name != NULL) {
&&&&&&&&&&& &&& delete []
&&&&&&& &&&&}
// protected:
&&&&&&&&char *name;
&&&&&&&&int age;
int main()
&&& Animal b =
&&& return 0;
我们往往被告知复制构造函数的格式是固定的,如下:
类名 (类名 &ref)
&&& ......
可是当时就没有想想它的形参为什么设计成引用类型,而不是对象或者指针类型呢?
首先,我想编译器这么规定是有他的道理的!! 以下愚见只供参考。
1) 引用比较高效:
&&& 如果形参是对象类型的,那么它是否也要实例化? 而且整个对象进行拷贝,效率不高,很不划算。
&&& 如果形参是指针类型的,从编译的角度来看 :
&&&&&&&& 程序在编译时分别将指针和引用添加到符号表上,符号表上记录的是变量名及变量所对应地址。指针变量在符号表上对应的地址值为指针变量的地址值,而引用在符号表上对应的地址值为引用对象的地址值。指针相当于中介,租房的时候直接跟房东谈比较划算 还是通过中介介绍划算,我想这个不用我说了吧(虽然我还没租过房)。
2) 形参为对象类型是行不通的:
&&&&& 复制构造函数也是构造函数,只不过它比较特别而已。上一条也提到了,如果形参是对象,在被调用时形参也需要实例化(构造)。 &&&&&& 那么它的构造是不是也有点类似于, 形参 = 实参 ;这么说来,这不是在调用复制构造函数麽? 之后调用复制构造函数的形参又要实例化,又调用复制构造函数,没完没了。在复制构造函数的形参中调用了自个儿,这不就是递归调用麽? 这还不怎么要紧,如果是我们平常使用递归往往会有出口点,但这里的是个死递归,这才要了命!(其实也要不了命,呵呵)
综上所述,以引用作为形参最为合适而且高效。
注:本博客的文章除注明有“转载”字样的外,均为原创,欢迎转载,请注明文字出处 & 谢谢!
阅读(5426) | 评论(0) | 转发(4) |
相关热门文章
给主人留下些什么吧!~~
请登录后评论。下次自动登录
现在的位置:
& 综合 & 正文
C++, C#引用的区别和C#的类为什么没有拷贝构造函数
不可否认,
在过去十年乃至现在一直都是
平台上的主流开发语言,而来势凶猛的
势必开辟一个崭新的局面,从目前的种种迹象来看,
是大势所趋,而
平台上的第一开发语言自然备受关注,于是有很多员纷纷转向
,这其中当然不乏
程序员。情况往往是这样,从一种语言过渡到另一种语言,哪怕是比较相似的语言,程序员也经常无意识地陷入原开发语言的思维定势,这样的结果通常只有一个,那就是导致连程序员自己也始终想不通的错误。本文由某
程序员提出的“难道
中没有拷贝构造函数?”这一问题引出
某些语言特性的对比。
一.发生了什么?
如果你是正在转向
程序员,你一定对
中的类没有拷贝构造函数和很少发生赋值运算符的调用感到不可理解,而且你看到的很多语句并不是像你想象的那样执行,比如
Student s1 = new Student() ;
Student s2 ;
此语句将发生什么?
因为你是一个熟练的
程序员,所以你在潜意识中就已经断定语句
将会在栈中生成一个
对象(即实例),而语句
将会调用赋值运算符。即上述语句执行完后,会产生如下内存布局
错了,全错了!!!
中却不是这样。我先解释上述语句在
中是怎样执行的。
Student s1 = new Student() ;
上面的将会在堆中生成一个对象,并且让引用
指向这个对象,而引用
本身位于栈中,占用四个字节(在
位处理器上,即一个指针的长度)。
Student s2 ;
该声明将会在栈中生成一个长度位
字节的引用变量
,并且缺省为
,即该引用不指向任何实例。
该赋值语句并没有调用赋值运算符,而是仅仅使
所指向的对象。所以上述语句执行完后,内存布局大致如下图
想要明白为什么,先要知道
引用的区别。
的引用区别
由上述简单的例子就会看到“引用”在
中的表现是多么的不一样,其主要区别可以表述为一句话:
中的引用是紧绑定的,而
中的引用是松绑定的。
中的引用使用“
”符号声明,而且声明时必须被初始化为一个有效的对象,而且引用一经初始化后,就不能再次赋值(即不能再令其指向其它对象),因此在
中编译器认为所有的引用都是有效的,不必进行类型检查等,这是
中引用没有指针灵活却比指针高效的原因。可以这么说,在
中,因为引用与对象是紧绑定的,我们可以认为引用就是对象本身。
正如栈对象的名字就是栈对象本身一样。也可以这么想,
中的引用只是某个对象的一个别名,这个名字仅仅因为这个对象的存在而存在。
Student s1 ;
Student& s2 = s1; //s2
Student s3 ;
非法!!!
不能再成为对象
将调用赋值运算符
中的紧绑定特性,所以上面最后一条语句会调用赋值运算符,使对象
处于一样的状态。
中只有两种类型的数据:值类型和引用类型。值类型通常是基本数据类型,如
等;而所有的自定义的类,还有数组、代表、接口等都是引用类型。由于这样的约定,所以你就不必对
”引用符而感到奇怪了。
所有的值类型对象永远只在栈中分配,即使你对值类型使用了
int age = new int(24) ;
仍然在栈中为
int age = 24 ;
同样所有引用类型对象永远只在堆中创建。要生成引用类型的实例一定要用
返回的引用通常保存在栈中。仅仅声明引用类型对象,就相当于声明了一个空指针(即
中的引用可以为空,这在
中是不允许的),只是在栈中分配了
个字节给这个引用,在该引用没有赋值之前(即没有指向有效的堆内存),不能使用该引用,因为该引用为空。
Student s5 ;
仅仅声明一个引用,并没有创建任何对象
s5 = new Student() ; //
在堆中创建一个对象,并让
指向该对象
中的引用更像
中的指针,也就是说
中的引用是具有指针语义的引用。
中的引用赋值就像
中的指针赋值一样,仅仅是让其指向另外的对象。也就是说
中使用的是最浅层次的拷贝。引用相互赋值时,仅仅是引用的值(表示逻辑内存地址数据)发生了改变,而对引用指向的对象的状态没有丝毫的影响――如果说有影响,那就是仅仅改变了
对该对象的引用计数。
中的引用具有指针的语义,才方便了
对对象的引用计数。当某个对象的引用计数变为
就会释放这个对象,这就是
中自动内存管理的基本原理。
三.引用传递和值传递
中按值传递对象时,会调用拷贝构造函数生成对象的副本,那么对应的
中也是这样的吗?
中,当变量或对象作为函数参数进行传递时都有两种方式:按值传递和按引用传递。
所谓按值传递是指在函数体内部使用的是对象的副本,在
中这个副本是调用对象的拷贝构造函数完成的,而函数对副本的修改不会影响原来的对象。如
void Fun1(Student ss)
进行处理和修改――实际处理的是传入对象的副本
Student s7 ;
Fun1(s7) ;//
此函数调用结束后,对象
的状态并没有改变
所谓按引用传递是指传给函数的实际上是对象的地址,这样函数对对象的修改就会反应在对象中,使对象的状态发生变化。如
void Fun2(Student& ss)
进行处理和修改
Student s8 ;
Fun2(s8) ;//
此函数调用结束后,对象
的状态发生改变
中,可以通过指针和“
”引用符实现引用传递。上面的例子用到了“
”引用符号,其实换成指针也可以达到同样的效果。如果我们再进一步去想,可以发现,当用指针进行引用传递时,也发生了复制,只不过复制的是指针的值(即对象的地址),而不是复制指针指向的对象。这可以通过如下例子得到证明。
void Fun3(Student* ss)
指向的对象进行处理和修改
ss = NULL ;
Student* s9 ;
Fun3(s9) ;//
此函数调用结束后,
指向的对象的状态发生了改变
)调用完后,
中使用的是指针
的副本。如果再进一步,我们可以猜测用“
”符实现引用传递时也发生了同样的故事。事实上也是这样,
中的引用只是一个受限却更加安全的指针而已。
那么按引用传递和按值传递各有什么好处了?
按引用传递不需要发生拷贝行为,因此速度快,特别是大对象时,这种优势很明显。按值传递时对传入对象的修改实际是对对象副本的修改,不会影响原对象的状态。
你也许会想到如果采用
引用传递那么就可以得到双倍的好处,可以这么说,但是不要走极端。
一般而言,将不允许改变的大对象作为
引用传递给函数是很合适的,但如果是简单类型或自定义的小对象直接用值传递就可以了。
如果外界一定要看到函数对对象的修改,那么只有一条路
按引用传递。
中情况却发生了变化,
中的引用类型的对象都是按引用传递且只能按引用传递。而值类型对象(或者称为变量),通常情况下是按值传递的。如果要按引用传递值类型对象,那么就要使用关键字
的唯一区别是
用修饰参数时要求传入的变量被初始化过。
由于类是引用类型,而所有的引用类型的对象的传递都是引用传递,所以在此过程中根本不会发生拷贝函数的调用。照这样看来,根本就没有必要有拷贝构造函数了。
我想现在你已经知道了
中为什么不需要拷贝构造函数和很少调用赋值运算符了。你也许会问既然是很少调用赋值运算符,那一定还有调用赋值运算符的情况存在,那么这种情况是怎样的?那是因为类的相仿体――结构
几乎没有任何差别,唯一的差别在于
的成员默认是公有的,而
的成员默认是私有的。然而情况在
中发生了本质的变化,因为
是值类型的,而
是引用类型的。从下面的分析可以看出
的创造者在这点设计上真是独具匠心。那么好处在哪里?
中所有值类型都在栈中创建,在栈中创建对象较之在堆中创建对象的优势在于:效率更高。因为在堆中分配对象之前要采用一定的寻找合适的内存块,而这可能是很费时间的,而创建值类型对象直接压栈就可以了;还有栈对象在函数返回时会自动释放,而堆对象要由
来处理。如果我们设计的是一个不太大的类,而且其实例很少在函数间传递(因为函数间按非引用传递值类型对象会发生复制),那么我们可以考虑将其实现为
是值类型,当两个同类型的
相互赋值时,自然就会调用
的赋值运算符。
另外,经过我的验证,在
中确实没有提供拷贝构造函数,但是你可以通过重载构造函数来变相地得到拷贝构造函数,这个技术的实现是很简单的,此处就不多说了。
讲到这里,已经差不多了,所以你不必在为像“为什么
中没有拷贝构造函数?”、“为什么
中很少看到赋值运算符的调用?”这样的问题而疑惑了
http://blog.csdn.net/zhuweisky/archive//415661.aspx
&&&&推荐文章:
【上篇】【下篇】

我要回帖

更多关于 未将对象引用到实例 的文章

 

随机推荐