C++拷贝对象
簡介
對象的創建中,常常有這樣的需求,就是把對象復制一份。
而復制有三種方法:
1.通過初始化來復制
例如:Object o1(10); Object o2=o1;
2.通過賦值來復制
例如:Object o1(10); Object o2; o2=o1;
3.通過默認拷貝函數來復制
例如:Object o1(10); Object o2(o1);
實際上,第一種方法內部原理是執行了第三種的拷貝函數,默認的拷貝函數是淺拷貝,也就是說只能對基本類型數值進行拷貝
Object類如下:
class Object {private:int _num;public:Object(int num){_num=num;}};分析
第一種復制對象方法原理(初始化復制)
1.首先 Object o2=o1 這句是先執行了o1的默認拷貝函數
此處o1的默認拷貝函數申明為: Object(const Object& obj),該實現體為編譯器默認的淺復制方法實現,因此對于含有復雜變量的類,需要重寫該函數
2.然后執行o1的拷貝函數后返回一個匿名對象
3.最后將該匿名對象命名為o2
第二種復制方法原理(賦值復制)
*該原理較為簡單,就是直接將簡單基本變量值拷貝一份賦值給拷貝對象
第三種復制方法原理(拷貝函數復制)
*第一種原理已解釋
實例
代碼
Object.h
class Object {private:int _num;public:Object(int num){_num=num;}int getNum(){return _num;}};main.cpp
#include <iostream> #include "Object.h" using namespace std;int main(int argc, char** argv) {Object o1(10);Object o2=o1;cout<<o2.getNum()<<endl;Object oo1(20);Object oo2(10);oo2=oo1;cout<<oo2.getNum()<<endl;Object ooo1(30);Object ooo2(ooo1);cout<<ooo2.getNum()<<endl;return 0; }運行結果
提升
代碼
Object.h
#ifndef OBJECT_H #define OBJECT_H#include <stdlib.h> #include <string.h>class Object {private:char *_name;public:Object(char *name){_name=(char*)malloc(sizeof(char)*(strlen(name)+1));strcpy(_name,name);}};#endifmain.cpp
#include <iostream> #include "Object.h" using namespace std;void Test() {Object o1("test");Object o2(o1); }int main(int argc, char** argv) {Test();return 0; }*這段代碼在較為嚴格的編譯器中會報錯,這是因為默認拷貝函數是淺拷貝,對基本的值進行拷貝
*然而o2拷貝o1的值時,拷貝的是_name的值,在棧中也就是字符串的地址值,因此拷貝后的o2的_name只是引用了o1的_name指向的字符串
*因此在Test函數結束時,首先o2被析構,其_name指向的字符串被回收。然后o1被析構,其_name指向的字符已在o2析構時被回收,因此o1的_name是野指針,因此產生錯誤。
改進代碼
Object.h
#ifndef OBJECT_H #define OBJECT_H#include <stdlib.h> #include <string.h>class Object {private:char *_name;int _num;public:Object(int num,char *name){_num=num;_name=(char*)malloc(sizeof(char)*(strlen(name)+1));strcpy(_name,name);}Object(const Object& obj){_name=(char*)malloc((sizeof(char)*strlen(obj._name)+1));strcpy(_name,obj._name);}};#endif轉載于:https://www.cnblogs.com/pwc1996/p/5957865.html
總結
- 上一篇: [ 1001] 动态开辟二维数组的说明
- 下一篇: Java常见问题汇总