C++基础 (3) 第三天 构造函数 构造函数初始化列表 拷贝构造函数 析构函数 静态成员变量
// 同类之间无私处
2构造函数

3析构函数

4构造函数的种类和析构函数的顺序
结论:析构函数的调用顺序,跟对象的构造顺序相反,谁先构造,谁最后一个被析构。



拷贝构造函数:

注意: 等号写在下面和写在上面是完全不同的。

5拷贝构造函数调用的发生场景



(注意这种情况的执行顺序, 在func函数执行的时候,调用了局部变量的拷贝构造函数

场景四:
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
using namespace std;
class Test
{
public:
// 默认构造函数,就是一个无参数的构造函数,
// 如果不显示提供构造函数 系统就是调用默认的构造函数 里面是空函数
// 如果我们提供了一个显示的构造函数,那么默认的构造函数就被隐藏掉了。
/*
Test(){} 默认的构造函数,已经手动提供,默认就被隐藏
*/
// 如果我们提供了一个显示的构造函数 那么默认的构造函数就被隐藏掉了
// 构造函数一旦手动提供 默认将不复存在
Test(int x, int y)
{
m_x = x;
m_y = y;
cout << "调用了有参数的构造函数" << endl;
}
// 无参数的构造函数
Test()
{
m_x = 0;
m_y = 0;
cout << "调用了无参数的构造函数" << endl;
}
// 拷贝构造函数 想通过另一个Test对象 another 将本对象进行拷贝
Test(const Test & another)
{
m_x = another.m_x;
m_y = another.m_y;
cout << "调用了拷贝构造函数" << endl;
}
// 等号操作符
void operator = (const Test & t)
{
m_x = t.m_x;
m_y = t.m_y;
}
void printT()
{
cout << "x: " << m_x << " ,y = " << m_y << endl;
}
// 提供一个析构函数
~Test()
{
cout << "~Test() 析构函数被执行了" << endl;
cout << "(" << m_x << "," << m_y << ")" << "被析构了" << endl;
}
private:
int m_x;
int m_y;
};
// 拷贝构造函数的第一个场景
void test1()
{
Test t1(1, 2);
Test t2(t1);
// 通过t1 给t2 进行赋值
t2.printT();
}
// 拷贝构造函数的第二个场景
void test2()
{
Test t1(1, 2);
Test t2;
t2 = t1; //调用的不是拷贝构造函数, 调用的是 =号操作符,也能够完成将t1的值给t2
// 但不是调用t2的拷贝构造函数
}
// 拷贝构造函数的第三个场景
void func(Test t) // Test t = test1::t1; // 会调用局部变量t的靠别构造函数
{
cout << "func begin..." << endl;
t.printT();
cout << "func end..." << endl;
}
void test3()
{
cout << "test3 begin ..." << endl;
Test t1(10, 20); //创建了一个t1的对象 通过t1的有参数的构造函数
func(t1);
cout << "test3 end..." << endl;
}
// 场景四
Test func2()
{
cout << "func2 begin..." << endl;
Test temp(10, 20);
cout << "func2 end.." << endl;
return temp; //有一个临时的匿名对象 = temp , 把temp的数据给到了临时的匿名对象
// 会调用这个临时匿名对象的拷贝构造函数 把temp传进去。
}
void test4() {
cout << "test4 begin..." << endl;
func2();
// 匿名对象在此被析构了 如果一个匿名的临时对象 没有任何变量去接受它
// 编译器认为这个临时匿名对象没有用处
// 编译器会立刻销毁这个临时的匿名对象
cout << "test4 begin..." << endl;
}
int main(void)
{
test4();
return 0;
}


(红圈表示匿名函数析构)
6默认构造函数和深拷贝浅拷贝




7中午回顾
// 浅拷贝析构的时候 可能会出现问题重复析构 两次 引出问题
8构造函数的初始化列表


结论:
// 类内部 的对象初始化的顺序 跟 对象定义的顺序一样 跟初始化列表中的顺序无关
// 析构的顺序就跟构造的顺序相反
9 强化练习1

12new和delete
new 和 delete
malloc 和 free
在堆上分配和释放的时候功能是类似的。
区别:new和delete会调用构造函数和析构函数
malloc和free不会
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
using namespace std;
class Test
{
public:
Test()
{
m_a = 0;
m_b = 0;
cout << "0,0 构造" << endl;
}
Test(int a, int b)
{
m_a = a;
m_b = b;
cout << "a = " << m_a << ", b = " << m_b << "构造" << endl;
}
void setA(int a)
{
m_a = a;
}
void setB(int b)
{
m_b = b;
}
void printT()
{
cout << "a = " << m_a << ", b =" << m_b << endl;
}
~Test()
{
cout << "a = " << m_a << ", b = " << m_b << "析构" << endl;
}
private:
int m_a;
int m_b;
};
// C语言中
void test1()
{
int *p = (int *)malloc(sizeof(int));
*p = 10;
cout << *p << endl;
if (p != NULL) {
//free(p);
delete p; // delete可以释放malloc开辟的内存
}
int *array_p = (int *)malloc(sizeof(int) * 10);
for (int i = 0; i < 10; i++)
{
array_p[i] = i + 10;
}
for (int i = 0; i < 10; i++)
{
cout << array_p[i] << endl;
}
if (array_p != NULL)
{
free(array_p);
}
cout << " ------- " << endl;
Test *tp = (Test *)malloc(sizeof(Test));// 不会调用对象的构造函数
tp->setA(10);
tp->setB(20); // malloc 出来的对象指针,只能够通过成员函数来进行初始化
tp->printT();
if (tp != NULL)
{
free(tp); //不会调用对象的析构
}
}
// malloc 和 free 在对于普通变量是可以混合使用的 但是malloc和free是函数
// new和delete是操作符。不是一个函数(没有压栈出栈过程)
// C++中的new delete
void test2()
{
//new 能够完成所有malooc的需求
int *p = new int; // 在堆上动态开辟4个字节
*p = 10;
cout << *p << endl;
if (p != NULL)
{
//delete p; //delete一个变量
free(p); //用new开辟的内存 free也能够释放
}
cout << "----" << endl;
int *array_p = new int[10];
for (int i = 0; i < 10; i++)
{
array_p[i] = i + 10;
}
for (int i = 0; i < 10; i++)
{
cout << array_p[i] << endl;
}
if (array_p != NULL)
{
delete[] array_p; // delete一个数组
}
cout << "------" << endl;
//Test *tp2 = new Test(10, 20); // 调用了有参数的构造函数//new 在创建一个对象的时候会调用对象的构造函数
Test *tp2 = new Test; //调用了无参构造函数
tp2->printT();
if (tp2 != NULL)
{
delete tp2; // delete在释放一个对象指针的时候 会调用对象的析构函数
}
}
int main(void)
{
//test1();
test2();
return 0;
}
13静态成员变量
在C语言中
static如果修饰全局变量 该变量不可以被别的文件访问
修饰局部变量 生命周期随着生命周期销毁销毁
修饰函数:
(普通 函数的定义和声明默认情况下是extern的,但静态函数只是在声明他的文件当中可见,不能被其他文件所用。因此定义静态函数有以下好处:
<1> 其他文件中可以定义相同名字的函数,不会发生冲突。
<2> 静态函数不能被其他文件所用。)
(static 貌似是在编译的时候就确定的,不是运行时)
复习:
https://www.cnblogs.com/getyoulove/p/3656184.html



共享同一块静态区域

14 static成员变量练习
定义 Box 所有的高度都一样



(通过查看大小 说明static修饰的成员变量不属于对象中,而是在全局区开辟的)
15 static修饰成员函数

main函数中:


(这里没有对象,是直接用类调用的)

16 static总结和static成员变量的大小



结论:决定类大小的就是类的普通成员变量 没有函数和全局变量
明天讲为什么
C++基础 (3) 第三天 构造函数 构造函数初始化列表 拷贝构造函数 析构函数 静态成员变量的更多相关文章
- C++构造函数初始化列表与构造函数中的赋值的区别
C++类中成员变量的初始化有两种方式:构造函数初始化列表和构造函数体内赋值. 一.内部数据类型(char,int……指针等) class Animal { public: Animal(int wei ...
- C++ 构造函数_初始化列表
构造函数初始化列表以一个冒号开始,接着是以逗号分隔的数据成员列表,每个数据成员后面跟一个放在括号中的初始化式.例如: class Student { public: //构造函数初始化列表 Stude ...
- C++(二十八) — 构造函数的初始化列表
1.解决的问题: 在 B 类中,组合了一个 A 类对象,其中A类设计了构造函数.由于构造函数的调用规则,设计了构造函数就必须调用,但在定义B类时没有机会初始化A,因此采用构造函数的初始化列表来解决. ...
- c++构造函数的初始化列表(翁恺c++公开课[13])
初始化列表形式: class Point { private: const float x,y; Point(float xa = 0.0, flato ya = 0.0):y(ya),x(xa) { ...
- C++ //构造函数调用规则 //1.创建一个类,C++编译器会给每个类添加至少3个函数 //默认构造(空实现) //析构函数(空实现) //拷贝函数(值拷贝) //2.如果我们写了有参构造函数 编译器就不会提供默认构造函数 但是会提供拷贝构造函数 //3.如果我们写了拷贝函数 编译器就不再提供 默认 有参 构造函数
//构造函数调用规则 #include <iostream> using namespace std; //1.创建一个类,C++编译器会给每个类添加至少3个函数 //默认构造(空实现) ...
- 【C++对象模型】构造函数语意学之二 拷贝构造函数
关于默认拷贝构造函数,有一点和默认构造函数类似,就是编译器只有在[需要的时候]才去合成默认的拷贝构造函数. 在什么时候才是[需要的时候]呢? 也就是类不展现[bitwise copy semantic ...
- c++ 关于类构造函数的初始化列表
除了性能问题之外,有些时场合初始化列表是不可或缺的,以下几种情况时必须使用初始化列表 常量成员,因为常量只能初始化不能赋值,所以必须放在初始化列表里面 引用类型,引用必须在定义的时候初始化,并且不能重 ...
- C++中构造函数的初始化列表(const、引用&变量初始化)
1. 构造函数执行分为两个阶段: a.初始化阶段(初始化) 初始化阶段具体指的是用构造函数初始化列表方式来初始化类中的数据成员. ClassXX:val(a),key(b){}; b.普通计算阶段(赋 ...
- 从初始化列表和构造函数谈C++的初始化机制
来源:http://blog.csdn.net/theprinceofelf/article/details/20057359 前段时间被人问及“初始化列表和构造有什么区别?”我竟一时语塞,只好回头 ...
随机推荐
- springcloud(一):Spring Cloud
研究了一段时间Spring Boot了准备向Spring Cloud进发,公司架构和项目也全面拥抱了Spring Cloud.在使用了一段时间后发现Spring Cloud从技术架构上降低了对大型系统 ...
- Shell、Xterm、Gnome-Terminal、Konsole简介(转)
什么是Shell? 简单的说, Shell就是一个小程序,这个小程序可以接受来自键盘的命令并把这些命令发送到操作系统,再有系统来执行.在过去,在安装有Unix的计算机上,这是唯一的可用的交互式操作.而 ...
- Android Studio 导入的项目编码错误问题
错误提示: Error:(4, 35) 閿欒: 缂栫爜UTF-8鐨勪笉鍙槧灏勫瓧绗? 解决方法: 1). 2). 的下面添加下面的一行语句: android{compileOptions.enco ...
- macOS10.9+xcode6编译ffmpeg2.4.2 for ios
近期须要用到ffmpeg开发视频相关.在网上找了些编译资源,自己摸索着,总算编译ok了. 因此,记录下苦逼的编译过程,已祭奠我为之逝去的青春. 1.准备工作 首先.到ffmpeg官网下载最新到代码. ...
- 线程同步、死锁和通信——Java多线程(二)
一.多线程同步 上一篇随笔中,我曾遇到对多线程程序的多次运行结果不一致的情况,这主要是因为没有对这些线程在访问临界资源做必要的控制,而接下来就用线程的同步来解决这个问题. 1.同步代码块 class ...
- 【iOS开发-80】Quartz2D画图简单介绍:直线/圆形/椭圆/方形以及上下文栈管理CGContextSaveGState/CGContextRestoreGState
watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvd2Vpc3ViYW8=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA ...
- 深入解析Dropout——基本思想:以概率P舍弃部分神经元,其它神经元以概率q=1-p被保留,舍去的神经元的输出都被设置为零
深度学习网络大杀器之Dropout——深入解析Dropout 转自:https://yq.aliyun.com/articles/68901 摘要: 本文详细介绍了深度学习中dropout技巧的思想 ...
- 南海区行政审批管理系统接口规范v0.3(规划)4.2.【queryExpireList】当天到期业务查询
加密前:{"time":"1510053168455","username":"GH_DATA_EXCHANGE",&q ...
- ES6和Node容易搞混淆的点
ES6 import 模块名 from XX '模块标识符' -----导入模块 import '路径 ' -----导入CSS样式 export default { } 和export ...
- mysql 操作提示 1366 Incorrect string value
一.报错说明 数据库此字段的字符集与整理字符集是否与SQL语句传递数据的字符集相同:不相同则会引发MySQL1366错误. 二.产生原因 windows 安装MySql 的时候选择的是默认的编码,创建 ...