C++ 对象的初始化与清理——详解构造、析构、拷贝函数的功能
内容导读
互联网集市收集整理的这篇技术教程文章主要介绍了C++ 对象的初始化与清理——详解构造、析构、拷贝函数的功能,小编现在分享给大家,供广大互联网技能从业者学习和参考。文章包含6160字,纯文字阅读大概需要9分钟。
内容图文
![C++ 对象的初始化与清理——详解构造、析构、拷贝函数的功能](/upload/InfoBanner/zyjiaocheng/640/86773aff2add4baa91caa37a50d63a84.jpg)
对象的初始化与清理
- 对于一个对象而言,如何设置最初的初始化参数与清理对象的数据呢?由次引入了两种函数——构造函数与析构函数。
1.1构造函数与析构函数
- 构造与析构函数本身是由编译器自动调用的,创建对象时调用构造函数,函数返回时在通过析构函数将对象内的数据进行一个销毁。如果不进行定义函数,编译器会自动调用空函数。
- 构造函数名称为类名称,析构函数名称为~类名称
//1、构造函数与析构函数
//析构函数在栈释放后执行
//构造与析构函数都是只执行一次,构造用于初始化,析构用于清除数据
class Person
{
public:
//构造函数
Person()
{
cout << "Person的构造函数调用" << endl;
}
//析构函数
~Person()
{
cout << "Person的析构函数调用" << endl;
}
};
void test01()
{
Person p;
}
int main() {
test01();
system("pause");
return 0;
}
1.2构造函数的分类与调用
- 构造函数分为有参数、无参数、拷贝函数三类。函数定义过程中无需写函数类型,也不用写return返回值
- 拷贝函数的意义在于将别的对象的参数进行拷贝,如下例子中person(const person &p)
- 调用方法分为括号法、显示、隐示三类方法。
//2、构造函数的分类与调用
#include <iostream>
using namespace std;
//1、构造函数分类
// 按照参数分类分为 有参和无参构造 无参又称为默认构造函数
// 按照类型分类分为 普通构造和拷贝构造
class Person {
public:
//无参(默认)构造函数
Person() {
cout << "无参构造函数!" << endl;
}
//有参构造函数
Person(int a) {
age = a;
cout << "有参构造函数!" << endl;
}
//拷贝构造函数
Person(const Person& p) {
age = p.age;
cout << "拷贝构造函数!" << endl;
}
//析构函数
~Person() {
cout << "析构函数!" << endl;
}
public:
int age;
};
//调用有参的构造函数
void test02() {
//2.1 括号法,常用
Person p0;
Person p1(10);
//注意1:调用无参构造函数不能加括号,如果加了编译器认为这是一个函数声明
//Person p2();
Person p2(p1);
//2.2 显式法
Person p3 = Person(10);
Person p4 = Person(p3);
//Person(10)单独写就是匿名对象 当前行结束之后,马上析构
//2.3 隐式转换法
Person p5 = 10; // Person p4 = Person(10);
Person p6 = p5; // Person p5 = Person(p4);
}
int main()
{
test02();
system("pause");
return 0;
}
1.3拷贝函数的调用
//3、拷贝函数调用的三种方式
class Person {
public:
Person() {
cout << "无参构造函数!" << endl;
mAge = 0;
}
Person(int age) {
cout << "有参构造函数!" << endl;
mAge = age;
}
Person(const Person& p) {
cout << "拷贝构造函数!" << endl;
mAge = p.mAge;
}
//析构函数在释放内存之前调用
~Person() {
cout << "析构函数!" << endl;
}
public:
int mAge;
};
//1. 使用一个已经创建完毕的对象来初始化一个新对象
void test01() {
Person man(100); //p对象已经创建完毕
Person newman(man); //调用拷贝构造函数
Person newman2 = man; //拷贝构造
//Person newman3;
//newman3 = man; //不是调用拷贝构造函数,赋值操作
}
//2. 值传递的方式给函数参数传值
//相当于Person p1 = p;
void doWork(Person p1) {}
void test02() {
Person p; //无参构造函数
doWork(p);
}
//3. 以值方式返回局部对象
Person doWork2()
{
Person p1;
cout << (int *)&p1 << endl;
return p1;
}
void test03()
{
Person p = doWork2();
cout << (int *)&p << endl;
}
int main() {
//test01();
//test02();
test03();
system("pause");
return 0;
}
1.4无参构造、有参构造、拷贝构造之间的调用规则
- 当自定义了有参构造的时候,无法调用其默认的无参构造,但仍可以调用编译器默认的拷贝构造。
- 当自定义了拷贝构造,其他的默认构造全部失效。
class Person {
public:
//无参(默认)构造函数
Person() {
cout << "无参构造函数!" << endl;
}
//有参构造函数
Person(int a) {
age = a;
cout << "有参构造函数!" << endl;
}
//拷贝构造函数
Person(const Person& p) {
age = p.age;
cout << "拷贝构造函数!" << endl;
}
//析构函数
~Person() {
cout << "析构函数!" << endl;
}
public:
int age;
};
void test01()
{
Person p1(18);
//如果不写拷贝构造,编译器会自动添加拷贝构造,并且做浅拷贝操作
Person p2(p1);
cout << "p2的年龄为: " << p2.age << endl;
}
void test02()
{
//如果用户提供有参构造,编译器不会提供默认构造,会提供拷贝构造
Person p1; //此时如果用户自己没有提供默认构造,会出错
Person p2(10); //用户提供的有参
Person p3(p2); //此时如果用户没有提供拷贝构造,编译器会提供
//如果用户提供拷贝构造,编译器不会提供其他构造函数
Person p4; //此时如果用户自己没有提供默认构造,会出错
Person p5(10); //此时如果用户自己没有提供有参,会出错
Person p6(p5); //用户自己提供拷贝构造
}
int main() {
test01();
system("pause");
return 0;
}
1.5浅拷贝与深拷贝
- 浅拷贝是指拷贝函数进行的是把原函数中的值进行拷贝,而深拷贝,是能够申请堆空间。
- 利用浅拷贝删除的时候会出现重复清理一个堆空间而报错的情况
//17、析构函数用来释放堆栈函数,若利用浅拷贝的话,会导致堆栈被两次释放,即重复释放,这时需要利用深拷贝来进行解决,深拷贝相比于浅拷贝的值传递,会在堆栈中重新申请空间。
class Person {
public:
//无参(默认)构造函数
Person() {
cout << "无参构造函数!" << endl;
}
//有参构造函数
Person(int age ,int height) {
cout << "有参构造函数!" << endl;
m_age = age;
m_height = new int(height);
}
//拷贝构造函数
Person(const Person& p) {
cout << "拷贝构造函数!" << endl;
//如果不利用深拷贝在堆区创建新内存,会导致浅拷贝带来的重复释放堆区问题
m_age = p.m_age;
m_height = new int(*p.m_height);
}
//析构函数
~Person() {
cout << "析构函数!" << endl;
if (m_height != NULL)
{
delete m_height;
}
}
public:
int m_age;
int* m_height;
};
void test01()
{
Person p1(18, 180);
Person p2(p1);
cout << "p1的年龄: " << p1.m_age << " 身高: " << *p1.m_height << endl;
cout << "p2的年龄: " << p2.m_age << " 身高: " << *p2.m_height << endl;
}
int main() {
test01();
system("pause");
return 0;
}
1.6初始化列表操作
class Person {
public:
////传统方式初始化
//Person(int a, int b, int c) {
// m_A = a;
// m_B = b;
// m_C = c;
//}
//初始化列表方式初始化
Person(int a, int b, int c) :m_A(a), m_B(b), m_C(c) {}
void PrintPerson() {
cout << "mA:" << m_A << endl;
cout << "mB:" << m_B << endl;
cout << "mC:" << m_C << endl;
}
private:
int m_A;
int m_B;
int m_C;
};
int main() {
Person p(1, 2, 3);
p.PrintPerson();
system("pause");
return 0;
}
1.7类中含类的构造析构顺序
在构造过程中,被包含的类先被构造,析构过程中,被包含的类后被析构
class Phone
{
public:
Phone(string name)
{
m_PhoneName = name;
cout << "Phone构造" << endl;
}
~Phone()
{
cout << "Phone析构" << endl;
}
string m_PhoneName;
};
class Person
{
public:
//初始化列表可以告诉编译器调用哪一个构造函数
Person(string name, string pName) :m_Name(name), m_Phone(pName)
{
cout << "Person构造" << endl;
}
~Person()
{
cout << "Person析构" << endl;
}
void playGame()
{
cout << m_Name << " 使用" << m_Phone.m_PhoneName << " 牌手机! " << endl;
}
string m_Name;
Phone m_Phone;
};
void test01()
{
//当类中成员是其他类对象时,我们称该成员为 对象成员
//构造的顺序是 :先调用对象成员的构造,再调用本类构造
//析构顺序与构造相反
Person p("张三" , "苹果X");
p.playGame();
}
int main() {
test01();
system("pause");
return 0;
}
内容总结
以上是互联网集市为您收集整理的C++ 对象的初始化与清理——详解构造、析构、拷贝函数的功能全部内容,希望文章能够帮你解决C++ 对象的初始化与清理——详解构造、析构、拷贝函数的功能所遇到的程序开发问题。 如果觉得互联网集市技术教程内容还不错,欢迎将互联网集市网站推荐给程序员好友。
内容备注
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 gblab@vip.qq.com 举报,一经查实,本站将立刻删除。
内容手机端
扫描二维码推送至手机访问。