??xml version="1.0" encoding="utf-8" standalone="yes"?>国产综合av,欧美日韩亚洲高清,在线国产亚洲欧美http://m.shnenglu.com/wstonep/Step By Stepzh-cnSun, 24 Aug 2025 05:09:45 GMTSun, 24 Aug 2025 05:09:45 GMT60【{】复制构造函敎ͼ拯构造函敎ͼhttp://m.shnenglu.com/wstonep/archive/2010/04/14/112536.htmlwstonepwstonepWed, 14 Apr 2010 03:03:00 GMThttp://m.shnenglu.com/wstonep/archive/2010/04/14/112536.htmlhttp://m.shnenglu.com/wstonep/comments/112536.htmlhttp://m.shnenglu.com/wstonep/archive/2010/04/14/112536.html#Feedback0http://m.shnenglu.com/wstonep/comments/commentRss/112536.htmlhttp://m.shnenglu.com/wstonep/services/trackbacks/112536.html转自此处Q貌似博M是{别h?/a>

也许很多C++的初学者都知道什么是构造函敎ͼ但是?span style="font-weight: bold;">复制构造函?/span>Qcopy constructorQ却q很陌生。对于我来说Q在写代码的时候能用得上复制构造函数的Zq不多,不过qƈ不说明复制构造函数没什么用Q其实复制构造函数能解决一些我们常怼忽略的问题?/font>
       Z说明复制构造函C用,我先说说我们在编E时会遇到的一些问题? 对于C++中的函数Q我们应该很熟悉了,因ؓq_l常使用Q对于类的对象,我们也很熟悉Q因为我们也l常写各U各Lc,使用各种各样的对象;对于指针? 操作Q我们也不陌生吧Q嗯Q如果你q不了解上面三个概念的话Q我惌文章不太适合你,不过看看也无^_^。我们经怋用函敎ͼ传递过各种各样的参数给 函数Q不q把对象Q注意是对象Q而不是对象的指针或对象的引用Q当作参Cl函数的情况我们应该比较遇见吧Q而且q个对象的构造函数还涉及C些内存分配的操作。嗯Q这样会有什么问题呢Q?/font>
       把参C递给函数有三U方法,一U是g?/span>Q一U是传地址Q?/span>q有一U? ?span style="font-weight: bold;">传引?/span>。前者与后两者不同的地方在于Q当使用g递的时候,会在函数里面生成传递参数的一个副?/span>Q这个副本的内容是按位从原始参数那里复制q来的,两? 的内Ҏ相同的。当原始参数是一个类的对象时Q它也会产生一个对象的副本Q不q在q里要注意。一般对象生时都会触发构造函数的执行Q但是在产生对象的副 本时却不会这Pq时执行的是对象的复制构造函数?/span>Z么会q样Q嗯Q一般的构造函数都是会完成一些成员属性初始化的工作,在对象传递给某一函数之前Q对 象的一些属性可能已l被改变了,如果在生对象副本的时候再执行对象的构造函敎ͼ那么q个对象的属性又再恢复到原始状态,qƈ不是我们惌的。所以在产生对象副本的时候,构造函C会被执行Q被执行的是一个默认的构造函数?span style="font-weight: bold;">当函数执行完毕要q回的时候,对象副本会执行析构函?/span>Q? 如果你的析构函数是空的话Q? ׃会发生什么问题,但一般的析构函数都是要完成一些清理工作,如释放指针所指向的内存空间。这时候问题就可能要出C。假如你在构造函数里面ؓ一个指? 变量分配了内存,在析构函数里面释攑ֈ配给q个指针所指向的内存空_那么在把对象传递给函数臛_数结束返回这一q程会发生什么事情呢Q首先有一个对象的 副本产生了,q个副本也有一个指针,它和原始对象的指针是指向同块内存I间的。函数返回时Q对象的析构函数被执行了Q即释放了对象副本里面指针所指向的内 存空_但是q个内存I间对原始对象还是有用的啊,q序本w而言Q这是一个严重的错误。然而错误还没结束,当原始对象也被销毁的时候,析构函数再次? 行,对同一块系l动态分配的内存I间释放两次是一个未知的操作Q将会生严重的错误?/font>
       上面说的是我们会遇到的问题。解决问题的Ҏ是什么呢Q首先我们想 到的是不要以传值的方式来传递参敎ͼ我们可以用传地址或传引用。没错,q样的确可以避免上面的情况,而且在允许的情况下,传地址或传引用是最好的ҎQ但 qƈ不适合所有的情况Q有时我们不希望在函数里面的一些操作会影响到函数外部的变量。那要怎么办呢Q可以利用复制构造函数来解决q一问题?span style="font-weight: bold;">复制构造函数就是在产生对象副本的时候执行的Q我们可以定义自q复制构造函数?span style="color: red;">在复制构造函数里面我们申请一个新的内存空间来保存构造函数里面的那个指针所指向的内?/span>。这样在执行对象副本的析构函数时Q释攄是复制构造函数里面所甌的那个内存空间?/font>
       除了对象传递给函数时会存在以上问题Q还有一U情况也会存在以上问题,是当函数返回对象时Q会产生一个时对?/span>Q这个时对象和对象的副本性质差不多?/font>
拯构造函?/span>Q经常被UCX(X&)Q是一U特D的构造函敎ͼ?span style="color: red;">q译器调用来完成一些基于同一cȝ其他对象的构件及初始化。它的唯一的一个参敎ͼ对象的引用)是不可变的(因ؓ是const型的Q。这个函数经常用在函数调用期间于用户定义cd的g递及q回?span style="color: red;">拯构造函数要调用基类的拷贝构造函数和成员函数。如果可以的话,它将用常量方式调用,另外Q也可以用非帔R方式调用?
在C++中,下面三种对象需要拷贝的情况。因此,拯构造函数将会被调用?
1)Q?一个对象以g递的方式传入函数?
2)Q?一个对象以g递的方式从函数返?
3)Q?一个对象需要通过另外一个对象进行初始化
? 上的情况需要拷贝构造函数的调用。如果在前两U情况不使用拯构造函数的时候,׃D一个指针指向已l被删除的内存空间?span style="color: red;">对于W三U情冉|_初始化和赋值的不同含义是构造函数调用的原因?/span>事实上,拯构造函数是由普通构造函数和赋值操作符共同实现的。描q拷贝构造函数和赋D符的异同的参考资料有很多?
拯构造函C可以改变它所引用的对?/span>Q其原因如下Q当一个对象以传递值的方式传一个函数的时候,拯构造函数自动的被调用来生成函数中的对象。如果一个对象是被传入自q拯构造函敎ͼ它的拯构造函数将会被调用来拷贝这个对象这样复制才可以传入它自q拯构造函敎ͼq会D无限? 环?
除了当对象传入函数的时候被隐式调用以外Q拷贝构造函数在对象被函数返回的时候也同样的被调用。换句话_你从函数q回得到的只是对象的一份拷贝。但是同LQ拷贝构造函数被正确的调用了Q你不必担心?
如果在类中没有显式的声明一个拷贝构造函敎ͼ那么Q编译器会私下里Z制定一个函数来q行对象之间的位拯Qbitwise copyQ。这个隐含的拯构造函数简单的兌了所有的cL员。许多作者都会提及这个默认的拯构造函数。注意到q个隐式的拷贝构造函数和昑ּ声明的拷贝构造函数的不同在于对于成员的关联方式。显式声明的拯构造函数关联的只是被实例化的类成员的缺省构造函数除非另外一个构造函数在cd始化或者在构造列表的时候被调用?
拯构造函CɽE序更加有效率,因ؓ它不用再构造一个对象的时候改变构造函数的参数列表。设计拷贝构造函数是一个良好的风格Q即使是~译pȝ提供的帮助你甌内存默认拯构造函数。事实上Q默认拷贝构造函数可以应付许多情c?/font>
附另外一关于复制构造函数的文章Q?/strong>

对一个简单变量的初始化方法是用一个常量或变量初始化另一个变量,例如Q?br>

int m = 80Q?br>int n = mQ?/span>

  我们已经会用构造函数初始化对象Q那么我们能不能象简单变量的初始化一P直接用一个对象来初始化另一个对象呢Q答案是肯定的。我们以前面定义的PointcMؓ例:
Point pt1(1525);
Point pt2 
= pt1;

后一个语句也可以写成Q?br>
Point pt2( pt1);

? 是用pt1初始化pt2Q此Ӟpt2各个成员的gpt1各个成员的值相同,也就是说Qpt1各个成员的D复制到pt2相应的成员当中。在q个初始? q程当中Q实际上调用了一个复制构造函数。当我们没有昑ּ定义一个复制构造函数时Q编译器会隐式定义一个缺省的复制构造函敎ͼ它是一个内联的、公有的? 员,它具有下面的原型形式Q?br>
Point:: Point (const Point &);

可见Q复制构造函C构造函数的不同之处在于形参Q前者的形参是Point对象的引用,其功能是一个对象的每一个成员复制到另一个对象对应的成员当中?br>  虽然没有必要Q我们也可以为PointcL式定义一个复制构造函敎ͼ
Point:: Point (const Point &pt)
{
  xVal
=pt. xVal;
  yVal
=pt. yVal;

如果一个类中有指针成员Q用缺省的复制构造函数初始化对象׃出现问题。ؓ了说明存在的问题Q我们假定对象A与对象B是相同的c,有一个指针成员,? 向对象C。当用对象B初始化对象AӞ~省的复制构造函数将B中每一个成员的值复制到A的对应的成员当中Q但q没有复制对象C。也是_对象A和对象B 中的指针成员均指向对象CQ实际上Q我们希望对象C也被复制Q得到C的对象副本D。否则,当对象A和B销毁时Q会对对象C的内存区重复释放Q而导致错误? Z使对象C也被复制Q就必须昑ּ定义复制构造函数。下面我们以stringcMؓ例说明,如何定义q个复制构造函数?

例题
?0-11
 
 1 class String
 2 {
 3  public:
 4   String(); //构造函?/span>
 5   String(const String &s); //复制构造函?/span>
 6   ~String(); //析构函数
 7 
 8   // 接口函数
 9   void set(char const *data);
10   char const *get(void);
11 
12  private:
13   char *str; //数据成员ptr指向分配的字W串
14 };
15 String ::String(const String &s)
16 {
17  str = new char[strlen(s.str) + 1];
18  strcpy(str, s.str);
19 }

我们也常用无名对象初始化另一个对象,例如Q?br>

Point pt = Point(1020);

  cd直接调用构造函数就生成了一个无名对象,上式用左边的无名对象初始化右边的pt对象?br>  构造函数被调用通常发生在以下三U情况,W一U情况就是我们上面看到的Q用一个对象初始化另一个对象时Q第二种情况是当对象作函数参敎ͼ实参传给形参ӞW三U情冉|E序q行q程中创建其它时对象时。下面我们再举一个例子,q二种情况和第三种情况q行说明Q?br>
Point foo(Point pt)
  {
   …
   
return pt;
  }
  
void main()
  {
   Point pt1 
= Point(1020);
   Point pt2;
   …
   pt2
=foo(pt);
   …
  }

  在main函数中调用foo函数Ӟ实参pt传给形参ptQ将实参pt复制lŞ参ptQ要调用复制构造函敎ͼ当函数fooq回Ӟ要创Z个pt的时对象,此时也要调用复制构造函数?

 

~省的复制构造函?br>  在类的定义中Q如果没有显式定义复制构造函敎ͼC++~译器会自动地定义一个缺省的复制构造函数。下面是使用复制构造函数的一个例子:

例题
?0-12
 
 1 #include <iostream.h>
 2 #include <string.h>
 3 class withCC
 4 {
 5  public:
 6  withCC(){}
 7  withCC(const withCC&)
 8  {
 9   cout<<"withCC(withCC&)"<<endl;
10  }
11 };
12 
13 class woCC
14 {
15  enum{bsz = 100};
16  char buf[bsz];
17 public:
18  woCC(const char* msg = 0)
19  {
20   memset(buf, 0, bsz);
21   if(msg) strncpy(buf, msg, bsz);
22  }
23  void print(const char* msg = 0)const
24  {
25   if(msg) cout<<msg<<":";
26   cout<<buf<<endl;
27  }
28 };
29 
30 class composite
31 {
32  withCC WITHCC;
33  woCC WOCC;
34 public:
35  composite() : WOCC("composite()"){}
36  void print(const char* msg = 0)
37  {
38   WOCC.print(msg);
39  }
40 };
41 
42 void main()
43 {
44  composite c;
45  c.print("contents of c");
46  cout<<"calling composite copy-constructor"<<endl;
47  composite c2 = c;
48  c2.print("contents of c2");
49 

cwithCC有一个复制构造函敎ͼcwoCC和类composite都没有显式定义复制构造函数。如果在cM没有昑ּ定义复制构造函敎ͼ则编译器自动地创徏一个缺省的构造函数。不q在q种情况下,q个构造函C么也不作?br>  ccomposite既含有withCCcȝ成员对象又含有woCCcȝ成员对象Q它使用无参的构造函数创建withCCcȝ对象WITHCCQ注意内嵌的对象WOCC的初始化ҎQ?br>  在main()函数中,语句Q?br>  composite c2 = c;
通过对象C初始化对象c2Q缺省的复制构造函数被调用?br>  最好的Ҏ是创q复制构造函数而不要指望编译器创徏Q这样就能保证程序在我们自己的控制之下?

wstonep 2010-04-14 11:03 发表评论
]]>
Never Too late to learnhttp://m.shnenglu.com/wstonep/archive/2010/04/13/112403.htmlwstonepwstonepMon, 12 Apr 2010 18:09:00 GMThttp://m.shnenglu.com/wstonep/archive/2010/04/13/112403.htmlhttp://m.shnenglu.com/wstonep/comments/112403.htmlhttp://m.shnenglu.com/wstonep/archive/2010/04/13/112403.html#Feedback0http://m.shnenglu.com/wstonep/comments/commentRss/112403.htmlhttp://m.shnenglu.com/wstonep/services/trackbacks/112403.html       不管怎样Q不能做饿死在干草堆之间的驴Q这个时候需要的是埋头苦吃!Q!



wstonep 2010-04-13 02:09 发表评论
]]>
þþþѾƷ| 77777ҹþö| þۺĻ| þӰۺ| þþƷž޾Ʒ| þݺҹҹ2020| ޾ƷŮþ777777| Ʒþþþþù| vĻþ | ľƷþþþ޲| þþƷѿ| ҹþþӰԺ| þݺҹҹav˳| þۺϾƷþ| ޹ۺϾþ| AëƬþþþƷëƬ| þþƷ | þþ뾫Ʒպ˳| AVݺɫۺϾþ| þþþþþ91Ʒѹۿ | Ůþþ| þۺϾƷ| 99þѹƷػ| ŷþþþþþѡ9999| LƷþ| ѹ99þþ㽶| þòӰ| þùƷ99Ʒ987| þó鱬Ļ| þþƷAVȫ| þ˽˹ƷvA| Ӱ7777þþƷ| Ʒʾþþþ999Ұ | 99þþƷѿһ| þþþ뾫Ʒapp| þ99ƷþþþþҰ| þþƷav| Ʒ˾þþ| ޹Ʒþþϼ2 | ˾þĻ| ݺݾþۺ|