0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看威廉希尔官方网站 视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

c++之对象构造顺序和销毁

电子设计 来源:电子设计 作者:电子设计 2020-12-24 17:20 次阅读

一、对象的构造顺序:

1、对于局部对象:

当程序执行流到达对象的定义语句时进行构造。下面还是用代码来解析这句话:

#include <stdio.h>
class Test

private:
int mi;
public
Test(int i)

mi=i;
printf("Test(int i) is %d",mi);

Test(const Test& obj)

mi=obj.mi;
printf("Test(const Test&) obj is %d",mi);

};
int main()

int i = 0 ;
Test a1 =i;//Test(int i):0
while(i<3)

Test a2 = ++i;//Test(int i):1,2,3

if(i<4)

Test a = a1; //Test(const Test& obj is :0

else

Test a(100);

return 0;

输出结果:

Test(int i) is 0
Test(int i) is 1
Test(int i) is 2
Test(int i) is 3
Test(const Test& obj) is 0

这里我们可以看出当程序流执行到相应的构造对象的那条执行语句时,就会调用构造函数(或者拷贝构造函数)。goto语句想必大家不陌生,但是都害怕这玩意,下面我们加入goto语句看看会产生什么现象:

#include <stdio.h>
class Test{
private:
int mi;
public:
Test(int i)

mi=i;
printf("Test(int i) is %d",mi);

Test(const Test& obj)

mi=obj.mi;
printf("Test(const Test& obj is %d",mi);

};
int main()

int i = 0; //Test(int i) :0
Test a1 = i;
while( i <3)

Test a2 = ++i; //Test(int i) :1,2,3

goto end;
if(i <4)

Test a = a1;//Test(const Test&) obj is :0

else

Test a(100);

end:
return 0;

输出结果:

Test(int i) is 0
Test(int i) is 1
Test(int i) is 2
Test(int i) is 3

从结果我们可以看出从if那条语句就被跳过了,没有执行到,这里这样写的目的是为了引出,当你使用goto语句,把对象给屏蔽了,后面你不能使用这个对象了,不然程序会出现大问题:

#include <stdio.h>
class Test{
private:
int mi;
public:
Test(int i)

mi=i;
printf("Test(int i) is %d",mi);

Test(const Test& obj)

mi=obj.mi;
printf("Test(const Test& obj is %d",mi);

int getMi()

return mi;

};
int main()

int i = 0; //Test(int i) :0
Test a1 = i;
while( i <3)

Test a2 = ++i; //Test(int i) :1,2,3

goto end;
Test a(100);
end:
printf("a.mi is %d",a.getMi());
return 0;

输出结果:

tt.cpp: In function ‘int main()’:
tt.cpp:32:1: error: jump to label ‘end’ [-fpermissive]
end:

tt.cpp:30:6: error: from here [-fpermissive]
goto end;

tt.cpp:31:12: error: crosses initialization of ‘Test a’
Test a(100);

这里就是上面所说了的,对象被goto语句给屏蔽了,后面就不能使用这个对象来进行操作了。

2、对于堆对象:

当程序执行流到达new语句时创建对象

使用new创建对象将自动触发构造函数的调用

代码演示:

#include <stdio.h>
class Test

private:
int mi;
public:
Test(int i)

mi = i;
printf("Test(int i): %d", mi);

Test(const Test& obj)

mi = obj.mi;
printf("Test(const Test& obj): %d", mi);

int getMi()

return mi;

};
int main()

int i = 0;
Test* a1 = new Test(i); // Test(int i): 0

while( ++i < 10 )
if( i % 2 )
new Test(i); // Test(int i): 1, 3, 5, 7, 9

if( i < 4 )
new Test(*a1);
else
new Test(100); // Test(int i): 100

return 0;

输出结果:

Test(int i): 0
Test(int i): 1
Test(int i): 3
Test(int i): 5
Test(int i): 7
Test(int i): 9
Test(int i): 100

3、对于全局对象:

对象的构造顺序是不确定的

不同的编译器使用不同的规则来确定构造顺序。

同样还是来看代码示例,这里我创建了几个文件:tes1.cpp test2.cpp test3.cpp test4.cpp test.h;他们的内容如下:

test1.cpp:

#include "test.h"
Test t4("t4");
int main()

Test t5("t5");

test2.cpp:

#include "test.h"
Test t1("t1");

test3.cpp:

#include "test.h"
Test t2("t2");

test4.cpp:

#include "test.h"
Test t3("t3");

test.h:

#ifndef _TEST_H_
#define _TEST_H_
#include <stdio.h>
class Test

public:
Test(const char* s)

printf("%s", s);

};
#endif

最后输出结果:

root@txp-virtual-machine:/home/txp# g++ test1.cpp test2.cpp test3.cpp test4.cpp -o put
root@txp-virtual-machine:/home/txp# ./put
t4
t1
t2
t3
t5

4、小结:

局部对象的构造顺序依赖程序的执行流

堆对象的构造顺序依赖于new的使用顺序

全局对象的构造顺序是不确定的

二、析构函数:

1、c++的类中可以定义一个特殊的清理函数,叫做析构函数,这个函数的功能与构造函数相反,顾名思义就是销毁的意思了。

2、定义:~ClassName()

析构函数没有参数也没有返回值类型声明

析构函数在对象销毁时自动被调用

代码示例:

#include <stdio.h>
class Test

int mi;
public:
Test(int i)

mi = i;
printf("Test(): %d", mi);

~Test()

printf("~Test(): %d", mi);

};
int main()

Test t(1);

Test* pt = new Test(2);

delete pt;

return 0;

输出结果:

Test(): 1
Test(): 2
~Test(): 2
~Test(): 1

3、析构函数的定义准则:

当类中自定义了构造函数,并且析构函数中使用了系统资源(比如说,内存的申请,文件打开),那么就需要自定义析构函数了。

4、小结:

析构函数是对象销毁时进行处理的特殊函数

析构函数在对象销毁时自动被调用

析构函数是对象释放系统资源的保障

审核编辑:符乾江
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 函数
    +关注

    关注

    3

    文章

    4329

    浏览量

    62575
  • C++
    C++
    +关注

    关注

    22

    文章

    2108

    浏览量

    73624
收藏 人收藏

    评论

    相关推荐

    运动控制卡周期上报实时数据IO状态C++

    使用C++进行运动控制卡的周期上报功能实现
    的头像 发表于 12-17 13:59 167次阅读
    运动控制卡周期上报实时数据IO状态<b class='flag-5'>之</b><b class='flag-5'>C++</b>篇

    同样是函数,在CC++中有什么区别

    同样是函数,在 CC++ 中有什么区别? 第一个返回值。 C语言的函数可以不写返回值类型,编译器会默认为返回 int。 但是 C++ 的函数,除了
    的头像 发表于 11-29 10:25 278次阅读

    C语言和C++中结构体的区别

    同样是结构体,看看在C语言和C++中有什么区别?
    的头像 发表于 10-30 15:11 199次阅读

    C7000优化C/C++编译器

    电子发烧友网站提供《C7000优化C/C++编译器.pdf》资料免费下载
    发表于 10-30 09:45 0次下载
    <b class='flag-5'>C</b>7000优化<b class='flag-5'>C</b>/<b class='flag-5'>C++</b>编译器

    ostream在c++中的用法

    ostream 是 C++ 标准库中一个非常重要的类,它位于 头文件中(实际上,更常见的是通过包含 头文件来间接包含 ,因为 包含了 和 )。 ostream 类及其派生类(如 std::cout
    的头像 发表于 09-20 15:11 681次阅读

    OpenVINO2024 C++推理使用技巧

    很多人都使用OpenVINO新版的C++ 或者Python的SDK,都觉得非常好用,OpenVINO2022之后的版本C++ SDK做了大量的优化与整理,已经是非常贴近开发的使用习惯与推理方式。与OpenCV的Mat对象对接方式
    的头像 发表于 07-26 09:20 888次阅读

    C++语言基础知识

    电子发烧友网站提供《C++语言基础知识.pdf》资料免费下载
    发表于 07-19 10:58 7次下载

    C++中实现类似instanceof的方法

    函数,可实际上C++中没有。但是别着急,其实C++中有两种简单的方法可以实现类似Java中的instanceof的功能。 在 C++ 中,确定对象的类型是编程中实际需求,使开发人员
    的头像 发表于 07-18 10:16 574次阅读
    <b class='flag-5'>C++</b>中实现类似instanceof的方法

    使用 MISRA C++:2023® 避免基于范围的 for 循环中的错误

    在前两篇博客中,我们 向您介绍了新的 MISRA C++ 标准 和 C++ 的历史 。在这篇博客中,我们将仔细研究以 C++ 中 for 循环为中心的特定规则。
    的头像 发表于 03-28 13:53 787次阅读
    使用 MISRA <b class='flag-5'>C++</b>:2023® 避免基于范围的 for 循环中的错误

    为什么很少用C++开发单片机

    C语言是面向过程的语言,C++是面向对象的编程语言。结合本文来说,面向过程相比面向对象的编程,生成代码量(bin文件)更小,运行效率更高。
    发表于 03-25 14:26 947次阅读
    为什么很少用<b class='flag-5'>C++</b>开发单片机

    c语言,c++,java,python区别

    操作系统、嵌入式系统等对性能要求较高的场景。C语言的语法相对简单,学习曲线较平缓,也是学习其他高级语言的入门语言。 C++C++是在C语言的基础上进行扩展和改进的一种编程语言。它支
    的头像 发表于 02-05 14:11 2370次阅读

    vb语言和c++语言的区别

    Microsoft开发的一种面向对象的事件驱动编程语言。它的设计目标是简化编程过程,让初学者也能快速上手。与相比,C++语言是一种通用的、面向对象的编程语言,其设计目标是提供高性能的
    的头像 发表于 02-01 10:20 2263次阅读

    C++简史:C++是如何开始的

    MISRA C++:2023,MISRA® C++ 标准的下一个版本,来了!为了帮助您做好准备,我们介绍了 Perforce 首席威廉希尔官方网站 支持工程师 Frank van den Beuken 博士撰写
    的头像 发表于 01-11 09:00 582次阅读
    <b class='flag-5'>C++</b>简史:<b class='flag-5'>C++</b>是如何开始的

    基于C/C++面向对象的方式封装socket通信类流程简析

    在掌握了基于 TCP 的套接字通信流程之后,为了方便使用,提高编码效率,可以对通信操作进行封装,本着有浅入深的原则,先基于 C 语言进行面向过程的函数封装,然后再基于 C++ 进行面向对象的类封装。
    的头像 发表于 12-26 10:00 1815次阅读

    基于C/C++面向对象的方式封装socket通信类

    在掌握了基于 TCP 的套接字通信流程之后,为了方便使用,提高编码效率,可以对通信操作进行封装,本着有浅入深的原则,先基于 C 语言进行面向过程的函数封装,然后再基于 C++ 进行面向对象的类封装。
    的头像 发表于 12-26 09:57 1332次阅读