700字范文,内容丰富有趣,生活中的好帮手!
700字范文 > 【拷贝构造函数 (浅)深拷贝 (浅)深赋值】

【拷贝构造函数 (浅)深拷贝 (浅)深赋值】

时间:2022-11-01 21:42:18

相关推荐

【拷贝构造函数 (浅)深拷贝 (浅)深赋值】

拷贝构造函数

同一个类的对象在内存中有完全相同的结构,如果作为一个整体进行复制或称拷贝是完全可行的。

这个拷贝过程只需要拷贝数据成员,而函数成员是共用的(只有一份拷贝)。在建立对象时可用同一类

的另一个对象来初始化该对象的存储空间,这时所用的构造函数称为拷贝构造函数(Copy

Constructor)。

using namespace std;class Empty{private:int value1;int value2;public:Empty() {}//构造函数~Empty() {}//析构函数Empty(const Empty&) {}//拷贝构造函数};

在类中如果没有显式给出拷贝构造函数时,则C++编译器自动给出一个缺省的拷贝构造函数。

using namespace std;class Empty{private:int value1;int value2;public:Empty(int x, int y) :value1(0) {value1 = x; value2 = y; }//构造函数~Empty() {}//析构函数void print()const{cout << "value1= " << value1 << "value2= " << value2 << endl;}};int main(){Empty a(2, 2);Empty b(33, 10);Empty c(0, 0);Empty d(b);d.print();return 0;}

打印结果:

如果我们给出了拷贝构造函数,那么则按函数重载的规律,调用合适的构造函数。

using namespace std;class Empty{private:int value1;int value2;int value3;//const char *a = "hello";public:Empty(int x, int y) :value1(0) {value1 = x; value2 = y; }~Empty() {}Empty(const Empty& x) :value1{3 }, value2{3 }{//value1 = x.value1;//value2 = x.value2;}void print()const{cout << "value1= " << value1 << "value2= " << value2 << endl;}};int main(){Empty a(2, 2);Empty b(33, 10);Empty c(0, 0);Empty d(a);//c = a + b;d.print();return 0;}

打印结果value1=3,value2=3。

class Empty{private:int value1;int value2;public:Empty() {}Empty(int x,int y) :value1(0) {value1 = x; value2 = y; }//构造函数~Empty() {}//析构函数Empty(const Empty&) {}//拷贝构造函数Empty& operator+(const Empty& x) {Empty tmp (x.value1 + value1, x.value2 + value2);return tmp;}//运算符重载函数:等号的赋值重载Empty* operator &() {return this; }//取地址函数const Empty* operator &()const {return this; }//引用运算符的重载:取地址void print()const{cout <<"value1= "<< value1 <<"value1= "<< value2 << endl;}};Empty &fun(int x, int y)//此处的返回值为什么不能是对象{Empty tmp(x,y);return tmp;}int main(){Empty a(2,2);Empty b(3,0);Empty e;e = fun(1234,5678);e.print();return 0;}

using namespace std;#if 1class Complex{private:int _Real;int _Image;public:Complex(int r = 0, int i = 0) :_Real(r), _Image(i){cout << "Create Complex" << this << endl;}~Complex() {cout << "Destroy Complex" << this << endl; }Complex(const Complex& cx) :_Real(cx._Real),_Image(cx._Image){cout << "Copy Create Complex" << this << endl; }void show(){cout << "_Real = " << _Real << " _Image = " << _Image << endl;}Complex operator=(const Complex & cx){if (this != &cx){_Real = cx._Real;_Image = cx._Image;}cout << "opreator =" << endl;return *this;}};int main(){Complex c1(1, 2);Complex c2(c1);Complex c3;c3 = c2;c3.show();return 0;}

下图输出的是 赋值重载函数返回值不加引用的情况:

Complex operator=(const Complex & cx)

而下图是 赋值重载函数返回值加引用的情况:

Complex & operator=(const Complex & cx)

由对比可以发现,当赋值重载函数返回值是对象时,当函数消亡之前,在主函数栈帧中创建一个临时的对象,把这个对象的成员一一赋值给C3后此临时对象就死掉了。

而当赋值重载函数返回值是对象的引用时,在函数退出之前不会创建一个临时对象,只返回对象(此this指针)的地址。

注意,当以引用返回时,一定注意此返回值是在哪儿定义的。当函数的生存期结束不影响此返回对象时,可以以引用返回。

深拷贝和浅拷贝

在这里插入代码片

深赋值和浅赋值

class MyString{char* str;public:MyString(const char* p = nullptr){if (p != nullptr){int n = strlen(p) + 1;str = new char[n];strcpy_s(str, n, p);}else{str = new char[1];str[0] = '\0';}cout << "Create MyString" << this << endl;}~MyString(){delete[]str;str = nullptr;cout << "Destroy MyString: " << this << endl;}MyString(const MyString& s){int n = strlen(s.str) + 1;str = new char[n];strcpy_s(str, n, s.str);cout << "Copy Create MyString: " << this << endl;}void Print() const{cout << str << endl;}MyString & fun(){MyString tmp("hello");return tmp;}int main(){MyString s1;s1.Print();s1 = fun();s1.Print();return 0;}

我们可以看到这里打印的不是hello而是随机值。为什么?

当我们用fun()函数去初始化s1时,函数结束返回时以引用的方式,返回的是一个地址,当函数结束,栈帧归还给系统。再次调用时这个地址就是一个悬空指针,所以打印随机值。

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。