C++ Primer笔记9_构造函数_拷贝构造(深拷贝与浅拷贝)

1.构造函数:


>构造函数是一个特殊的、与类同名的成员函数,用于给每个成员设置适当的初始值。

  1. >构造函数不能有返回值,函数名与类名相同。

  2. >缺省构造函数时,系统将自动调用该缺省构造函数初始化对象,缺省构造函数会将所有数据成员都初始化为零或       空。缺省构造函数是不带参数的构造函数。

  3. >创建一个对象时,系统自动调用构造函数。


构造函数的特点:

     1.构造函数可以重载,传入什么实参决定调用不同版本的构造函数。

     2.构造函数不能声明为const 、也不能声明为virtual;(析构函数可以)

     3.一个类如果自定义了一个构造函数,编译器就不会生成默认构造函数。

     4.只有构造函数才有类似初始化列表的形式来初始化成员变量(特别是const成员变量只能在初始化列表中初始化)


例子:

#include <iostream>
#include <new>

class Person
{
public:
	Person();//默认的构造函数
	Person(int n, const string &str);//构造函数的重载
private:
	int age;
	string *name;
};



2.拷贝构造


先介绍一下深拷贝浅拷贝

>浅拷贝: 指的是在对象复制时,只对对象中的数据成员进行简单的赋值;默认拷贝构造函数执行的也是浅拷贝。        大多情况下“浅拷贝”已经能很好地工作了,但是一旦对象存在了动态成员,那么浅拷贝就会出问题了。

>深拷贝:当类的成员变量有指针类型时,拷贝对象时应该为指针变量重新分配好空间,避免浅拷贝中只拷贝指针的    值,使得两个指针指向同一块内存空间。


浅拷贝缺陷例子:

#include <iostream>
#include <new>

using namespace std;

class Person
{
public:
	Person();
	Person(int n, const string &str);//构造函数重载
	~Person();
private:
	int age;
	string *name;
};

Person::Person():age(0), name(NULL)//构造函数初始化列表,定义时不必写!
{
	cout << "Default Person" << endl;
}

Person::Person(int n, const string &str):age(n), name(new string(str))
{
	cout << "Init Person" << endl;
}

Person::~Person()
{
	if(name)
	{
		cout << "~Person " << "name: " << *name << " age: " << age << endl;
	}
	delete name;
}

int main()
{
	Person p1(10, string("SCOTT"));
	Person p2 = p1;

	return 0;
}

运行结果:

Init Person
~Person name: SCOTT age: 10
Segmentation fault (core dumped)

程序崩溃原因:

       p2由p1初始化而得到,由于我们没有自定义拷贝构造函数,所以调用的是默认的拷贝构造函数,属于浅拷贝,只对name的值进行了拷贝;p1与p2中的name指针指向同一个new空间,最后调用析构函数时,会造成两次delete而出现段错误。

如下图所示:




解决方法:自定义拷贝构造函数! 达到深拷贝的效果

深拷贝例子:

#include <iostream>
#include <new>

using namespace std;

class Person
{
public:
	Person();
	Person(int n, const string &str);
	Person(const Person &n);
	~Person();
private:
	int age;
	string *name;
};

Person::Person():age(0), name(NULL)
{
	cout << "Default Person" << endl;
}

Person::Person(int n, const string &str):age(n), name(new string(str))
{
	cout << "Init Person" << endl;
}
//自定义拷贝构造函数
Person::Person(const Person &n)
{
	if(n.name)
	{
		name = new string(*n.name);
		age = n.age;
	}
}

Person::~Person()
{
	if(name)
	{
		cout << "~Person " << "name: " << *name << " age: " << age << endl;
	}
	delete name;
}

int main()
{
	Person p1(10, string("SCOTT"));
	Person p2 = p1;

	return 0;
}

运行结果:

Init Person

~Person name: SCOTT age: 10

~Person name: SCOTT age: 10
没有出现段错误,由此可见,上述解决方案可行。





  • 3
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值