栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

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

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

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

拷贝构造函数

同一个类的对象在内存中有完全相同的结构,如果作为一个整体进行复制或称拷贝是完全可行的。
这个拷贝过程只需要拷贝数据成员,而函数成员是共用的(只有一份拷贝)。在建立对象时可用同一类
的另一个对象来初始化该对象的存储空间,这时所用的构造函数称为拷贝构造函数(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 1
class 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)

blog.csdnimg.cn/fc7250602e174f8980bff704860c1b47.png)" />

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

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] = '';
		}
		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时,函数结束返回时以引用的方式,返回的是一个地址,当函数结束,栈帧归还给系统。再次调用时这个地址就是一个悬空指针,所以打印随机值。

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/982613.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号