c构造函数详解_构造函数有什么用

c构造函数详解_构造函数有什么用c++构造函数详解。(构造函数的分类、拷贝构造函数)

大家好,又见面了,我是你们的朋友全栈君。如果您正在找激活码,请点击查看最新教程,关注关注公众号 “全栈程序员社区” 获取激活教程,可能之前旧版本教程已经失效.最新Idea2022.1教程亲测有效,一键激活。

Jetbrains全系列IDE使用 1年只要46元 售后保障 童叟无欺

c++ 构造函数详解

构造函数是干什么的

  • 该类对象被创建的时候,编译系统对象分配内存空间,并自动调用该构造函数,由构造函数完成成员的初始化工作,故:构造函数的作用:初始化对象的数据成员

构造函数的分类

  • 无参构造函数
  • 带默认值的构造函数
  • 有参(无默认值)的构造函数
  • 复制构造函数(拷贝构造函数)
    • 一种特殊的构造函数,当对象之间复制时会自动调用拷贝构造函数
    • 若类中没有显示定义拷贝构造函数,则系统会自动生成默认拷贝构造函数
	#include <iostream>
using namespace std;
class Coordinate
{ 

public:
// 无参构造函数
// 如果创建一个类你没有写任何构造函数,则系统自动生成默认的构造函数,函数为空,什么都不干
// 如果自己显示定义了一个构造函数,则不会调用系统的构造函数
Coordinate()
{ 

c_x = 0;
c_y = 0;
}     
// 一般构造函数
Coordinate(double x, double y):c_x(x), c_y(y){ 
}   //列表初始化
// 一般构造函数可以有多个,创建对象时根据传入的参数不同调用不同的构造函数
Coordinate(const Coordinate& c)
{ 

// 复制对象c中的数据成员
c_x = c.c_x;
c_y = c.c_y;
}
// 等号运算符重载
Coordinate& operator= (const Coordinate& rhs)
{ 

// 首先检测等号右边的是否就是等号左边的对象本身,如果是,直接返回即可
if(this == &rhs)
return* this;
// 复制等号右边的成员到左边的对象中
this->c_x = rhs.c_x;
this->c_y = rhs.c_y;
return* this;
}
double get_x()
{ 

return c_x;
}
double get_y()
{ 

return c_y;
}
private:
double c_x;
double c_y;
};
int main()
{ 

// 调用无参构造函数,c1 = 0,c2 = 0
Coordinate c1, c2;
// 调用一般构造函数,调用显示定义构造函数
Coordinate c3(1.0, 2.0);
c1 = c3;    //将c3的值赋值给c1,调用"="重载
Coordinate c5(c2);
Coordinate c4 = c2;    // 调用浅拷贝函数,参数为c2
cout<<"c1 = "<<"("<<c1.get_x()<<", "<<c1.get_y()<<")"<<endl
<<"c2 = "<<"("<<c2.get_x()<<", "<<c2.get_y()<<")"<<endl
<<"c3 = "<<"("<<c3.get_x()<<", "<<c3.get_y()<<")"<<endl
<<"c4 = "<<"("<<c4.get_x()<<", "<<c4.get_y()<<")"<<endl
<<"c5 = "<<"("<<c5.get_x()<<", "<<c5.get_y()<<")"<<endl;
return 0;
}
	c1 = (1, 2)
c2 = (0, 0)
c3 = (1, 2)
c4 = (0, 0)
c5 = (0, 0)
请按任意键继续. . .

拷贝构造函数

  • 拷贝构造函数是一种特殊的构造函数,具有单个形参,该形参(常用const修饰)是对该类型的引用。当定义一个新对象并用同一类型的对象都它进行初始化时,将显示使用拷贝构造函数,当该类型的对象传递给函数返回该类型的对象时,将隐式调用拷贝构造函数
  • 当类中有一个数据成员是指针时,或者有成员表示在构造函数中分配的其他资源,必须显示定义拷贝构造函数
  • 构造函数的使用情况
    • 一个对象以值传递的方式传入函数体
    • 一个对象以值传递的方式从函数体返回
    • 一个对象需要通过另一个对象进行初始化
	#include <iostream>
using namespace std;
class Test
{ 

public:
// 构造函数
Test(int a):t_a(a){ 

cout<<"creat: "<<t_a<<endl;
}
// 拷贝构造函数
Test(const Test& T)
{ 

t_a = T.t_a;
cout<<"copy"<<endl;
}
// 析构函数
~Test()
{ 

cout<<"delete: "<<t_a<<endl;
}
// 显示函数
void show()
{ 

cout<<t_a<<endl; 
}
private:
int t_a;
};
// 全局函数,传入的是对象
void fun(Test C)
{ 

cout<<"test"<<endl;
}
int main()
{ 

Test t(1);
// 函数中传入对象
fun(t);
return 0;
}
	creat: 1
copy
test
delete: 1
delete: 1
请按任意键继续. . .

浅拷贝与深拷贝

  • 浅拷贝
    • 所谓浅拷贝,指的是在对象复制时,只对对象中的数据成员进行简单的赋值,默认拷贝构造函数执行的也是浅拷贝。也就是增加了一个指针,指向原来已经存在的内存。 正常情况下,“浅拷贝”已经能很好的工作,但是一旦对象存在动态成员,浅拷贝就会出问题。让我们考虑下面一段代码:
	#include <iostream>
#include <assert.h> 
using namespace std;
class Test
{ 

public:
Test(){ 

p = new int(10);
}
~Test(){ 

assert(p != NULL);     // assert()作用是如果他的条件返回错误,则终止程序执行 
delete p;
}
private:
int x;
int y;
int* p;
};
int main()
{ 

Test t1;
Test t2(t1);    // 调用默认拷贝构造函数
return 0;
}

上述程序崩溃。在使用t1复制t2时,进行的是浅拷贝,只是将成员的值进行赋值。此时,t1.p = t2.p, 即两个指针指向了堆里的同一个空间。这样,析构函数会被调用两次,这就是错误出现的原因。此问题的解决方法是“深拷贝”。

  • 深拷贝
    • 深拷贝就是对于对象中的动态成员,并不只是简单的赋值,而是重新分配空间,即资源重新分配。上述代码处理如下:
	#include <iostream>
#include <assert.h> 
using namespace std;
class Test
{ 

public:
Test(){ 

x = 0;
y = 0;
p = new int(10);
}
Test(const Test& t)
{ 

x = t.x;
y = t.y;
p = new int(10);
*p = *(t.p);
}
~Test(){ 

assert(p != NULL);     // assert()作用是如果他的条件返回错误,则终止程序执行 
delete p;
}
int get_x(){ 
return x;}
int get_y(){ 
return y;}
private:
int x;
int y;
int* p;
};
int main()
{ 

Test t1;
Test t2(t1);    // 调用默认拷贝构造函数
cout<<"("<<t1.get_x()<<", "<<t1.get_y()<<")"<<endl
<<"("<<t2.get_x()<<", "<<t2.get_y()<<")"<<endl;
return 0;
}
(0, 0)
(0, 0)
请按任意键继续. . .

此时t1与t2的p各自指向一段内存空间,但他们指向的内容相同,这就是“深拷贝”。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/195919.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)


相关推荐

  • java 接口学习

    你应该知道接口是一种契约,它与实现方式无关但是类,即使是抽象类,你都能自定义成员变量,而成员变量往往就与实现方式有关。这一点的实际意义不大。但是有一点,类会暴露太多不必要,甚至不能暴露的东西,你

    2021年12月22日
  • 字符串分割方法代码

    字符串分割方法代码

  • 互联网快讯:华为云正式推出区块链服务;猿辅导布局素质教育;轻松筹回应裁员

    互联网快讯:华为云正式推出区块链服务;猿辅导布局素质教育;轻松筹回应裁员国内要闻1、HarmonyOS2升级用户数突破1.2亿,平均每天超100万用户升级2、华为云正式推出区块链服务,单链支持每秒5万条商品信息上链3、荣耀CEO赵明:未来可能有上市计划,星耀公司不是荣耀子品牌4、顺丰回应被浙江省消保委点名:拟于9月29日下架“签收确认”增值服务产品5、轻松筹回应裁员:系因业务调整,所有人将按法律规定结算项目工资6、阿里云推出全球首个云定义存储产品,性能大幅提升300%教育培训1、国家发改委价格司:加强学科类校外培训收费监管工作2、猿辅

  • OV7725鹰眼摄像头

    OV7725鹰眼摄像头OV7725鹰眼摄像头如何使用?目前的ov7725鹰眼摄像头,基本上用的都是山外的库,所以今天我们主要根据山外的库,基于k60芯片,给大家具体的讲解。1.摄像头初始化首先是摄像头的第一步就是初始化,这个我们直接去调用就行!camera_init(imgbuff);当然小伙伴在这里需要记住,需要配置中断优先级!对于我们使用摄像头的车而言,一般优先级最高的就是摄像头,所以小伙伴要记着给它分配优先级!我这里是分了五个优先级!大家也可以根据自己的需求,进行自主分配。NVIC_SetPriorit

  • Delphi XE5 FireMonkey移动开发示例:粒子系统

    Delphi XE5 FireMonkey移动开发示例:粒子系统这个例子是参照Processing中的例子写的。  测试结果:在Windows7上,脱离开发环境的性能与Processing相当,在Android上表现良好。 源码如下:  unitExample.Particles;interfaceusesSystem.SysUtils,System.Types,System.UITypes,System.Classes,

  • SQL 聚合函数之字符串分组合并[通俗易懂]

    SQL 聚合函数之字符串分组合并[通俗易懂]本文介绍了如何通过SQL函数对字符串进行聚合,也就是将多行字符串合并成单个字符串。包括Oracle(LISTAGG函数)、MySQL(GROUP_CONCAT函数)、SQLServer(STRING_AGG函数)、PostgreSQL(STRING_AGG函数)以及SQLite(GROUP_CONCAT函数)的语法和差异。

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号