??xml version="1.0" encoding="utf-8" standalone="yes"?> 对一个简单变量的初始化方法是用一个常量或变量初始化另一个变量,例如Q?br>
也许很多C++的初学者都知道什么是构造函敎ͼ但是?span style="font-weight: bold;">复制构造函?/span>Qcopy constructorQ却q很陌生。对于我来说Q在写代码的时候能用得上复制构造函数的Zq不多,不过qƈ不说明复制构造函数没什么用Q其实复制构造函数能解决一些我们常怼忽略的问题?/font>
在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那么我们能不能象简单变量的初始化一P直接用一个对象来初始化另一个对象呢Q答案是肯定的。我们以前面定义的PointcMؓ例:
Point pt2 = pt1;
后一个语句也可以写成Q?br>
?
是用pt1初始化pt2Q此Ӟpt2各个成员的gpt1各个成员的值相同,也就是说Qpt1各个成员的D复制到pt2相应的成员当中。在q个初始?
q程当中Q实际上调用了一个复制构造函数。当我们没有昑ּ定义一个复制构造函数时Q编译器会隐式定义一个缺省的复制构造函敎ͼ它是一个内联的、公有的?
员,它具有下面的原型形式Q?br>
可见Q复制构造函C构造函数的不同之处在于形参Q前者的形参是Point对象的引用,其功能是一个对象的每一个成员复制到另一个对象对应的成员当中?br> 虽然没有必要Q我们也可以为PointcL式定义一个复制构造函敎ͼ
{
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>
~省的复制构造函?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 } |
|
![]() |