析构函数

C++ RAII 与 ScopeGuard

☆樱花仙子☆ 提交于 2019-12-06 14:35:27
C++ RAII 与 ScopeGuard RAII机制 RAII(Resource Acquisition Is Initialization),也就是“资源获取就是初始化”,是C++语言的一种管理资源、避免泄漏的惯用法。C++标准保证任何情况下,已构造的对象最终会销毁,即它的析构函数最终会被调用。简单的说,RAII 的做法是使用一个对象,在其构造时获取资源,在对象生命期控制对资源的访问使之始终保持有效,最后在对象析构的时候释放资源。 当我们在一个函数内部使用局部变量,当退出了这个局部变量的作用域时,这个变量也就别销毁了;当这个变量是类对象时,这个时候,就会自动调用这个类的析构函数,而这一切都是自动发生的,不要程序员显示的去调用完成。这个也太好了,RAII就是这样去完成的。 由于系统的资源不具有自动释放的功能,而C++中的类具有自动调用析构函数的功能。 如果把资源用类进行封装起来,对资源操作都封装在类的内部,在析构函数中进行释放资源。当定义的局部变量的生命结束时,它的析构函数就会自动的被调用,如此,就不用程序员显示的去调用释放资源的操作了。 RAII 过程可以分为四个步骤: 设计一个类封装资源; 在构造函数中初始化; 在析构函数中执行销毁操作; 使用时声明一个该对象的类; 先看一个不使用RAII的例子,在下面的 UseFile函数中: void UseFile(char

类的构造和析构

送分小仙女□ 提交于 2019-12-06 08:50:29
类的构造和析构 类对象不能用列表初始化是因为数据访问状态为私有。 如果将访问状态改为公有,那么就可以使用大括号初始化的方法。但是违背了数据隐藏的初衷。 声明和定义构造函数 声明,其中可以包含默认参数 Stock(const string & co, long n = 0, double pr = 0.0); 定义 Stock::Stock(const string & co, long n, double pr) { ... } 为避免成员名和参数名混乱,常见的做法是在成员名前加m_前缀或加_后缀。 使用构造函数 c++提供两种使用构造函数来初始化对象的方式。第一种是显式的调用构造函数。 Stock food = Stock("yang", 29, 1.2); 另一种是隐式的调用 Stock food("yang", 29, 2.1); 使用new分配内存时,c++都使用构造函数。在这种情况下,该对象没有名字,但可以使用指针来管理对象。 Stock *food = new Stock("yang", 29, 1.2); 默认构造函数 默认构造函数是在未提供显式初始值时,用来创建对象的构造函数。 Stock food; 当且仅当没有定义构造函数时,编译器才会提供默认构造函数。 为类定义了构造函数后,就必须提供默认构造函数。否则该声明会出错。Stock food;

不在构造函数和析构函数中调用virtual函数

大城市里の小女人 提交于 2019-12-06 08:44:46
1.不在构造函数中调用virtual函数 例如 class Base{ public: Base(); virtual void func1() const=0; } Base::Base() { //... func1(); } class Derived:public Base { public: virtual void func1() const; } 当Derived d被执行时,首先调用的是基类Base的构造函数,在Base构造函数内调用func1是不合适的,因为func1在基类中是一个纯虚函数,没有定义,此时的子类Derived对象还没有被建立。也就是执行基类的构造函数时,该对象的派生类部分是为被初始化的状态; 如果在构造函数中想要调用子类中的接口,可以通过将子类的信息传递到父类中的构造函数中去,例如: class Base { public: Base(String str); void func1(String str); } Base(String str) { //.... func1(str); } class Derived:public Base { public: Derived (str) :Base(str) {//.....} } 2.在析构函数中调用虚函数也没有意义 销毁派生类对象的次序和构造函数时的次序相比正好是相反的

一次电话面试题

我与影子孤独终老i 提交于 2019-12-06 07:06:25
C++中引用与指针的区别? https://blog.csdn.net/zhengqijun_/article/details/54980769 大小端这个问题在面试过程中偶尔会被问到 第一种:联合(union)方式判断法 在union中所有的数据成员共用一个空间,同一时间只能储存其中一个数据成员,所有的数据成员具有相同 的起始地址。即上述的union虽然定义了两个成员,但其实这个union只占用了4个字节(32位机器中),往a成员 赋值,然后读取b就相读取a成员的低位第一个字节的值。如果机器使用大端模式,则u.a=1那a的最高字节值为1; 如果机器使用小段模式,则u.a=1则a的最低位字节为1。上述可知b和a有相同的起始位,所以读取b如果等于1, 则为小端模式,b为0则为大端模式 typedef union { int i; char c; }my_union; int checkSystem1(void) { my_union u; u.i = 1; return (u.i == u.c); } 第二种称之为直接判断法,怎么直接判断呢,其实就是根据大小端各自的存储方式编写程序进行判断,这个方法更直接。 首先我们来看下大小端的存储方式: 大端模式(Big_endian) -- 字数据的高字节存储在低地址中,而字数据的低字节则存放在高地址中。 小端模式(Little_endian)

继承设计

荒凉一梦 提交于 2019-12-06 04:59:04
1 .回顾类和对象的创建 定义学生类Student,包含私有数据成员:num(学号)、name(姓名,字符数组)、age(年龄);公有成员函数:Student(构造函数)、~Student(析构函数),使用构造函数为Student类对象的数据成员赋值 (name使用动态内存分配),在析构函数中释放动态分配的内存 ,显示函数display(显示学生信息)。 法一: #include<iostream> #include<string> using namespace std; class Student { private: long num; char* name; int age; public: Student() {} Student(long nu, char* na, int a) :num(nu), name(na), age(a) {} ~Student() {} void display() { cout << "学号:" << num << " " << endl << "姓名:" << name << endl << "年龄:" << age << endl; } }; int main() { char ch[] = "李丽"; Student* ptr = new Student();//① ptr = new Student(3018314, ch, 18

C#学习系列(一)——C#和C++的区别

倖福魔咒の 提交于 2019-12-05 22:13:34
C#和C++的区别在于:C#代码首先会被编译为CLR(公共语言运行库),然后由.NET框架解析;它是在虚拟机上执行,会自动进行内存管理,不支持使用指针。C++将会直接被编译为机器代码,允许使用指针,需要手动组织管理内存。 C#和C ++的区别 1、编译区别 C#代码首先会被编译为CLR(公共语言运行库),然后由.NET框架解析。 C ++代码将会直接被编译为机器代码。 2、内存管理的不同 C#是在虚拟机上执行,会自动进行内存管理。而,C ++需要手动组织管理内存。 3、指针使用的区别 C#不支持使用指针,但可以使用一些不安全的类和方法;而,C ++允许使用指针。 4、系统环境(平台)的区别 C#主要用于Windows环境;而,C ++是为基于Unix的系统设计的,但现在可以用于任何平台。 5、应用上的区别 C#的应用涉及基于Web的桌面和移动应用程序;而,C ++的唯一目的就是创建独立的控制台应用程序。 6、速度上的区别 C ++代码更快,因为它不使用重型库;而,C#较慢,因为它会产生开销并使用了类似于java这样的重型库。 C与C++的区别 1. C 语言是面向过程的,而 C++ 是面向对象的。 2,C 语言有标准的函数库,它们松散的,只是把功能相同的函数放在一个头文件中;而 C++ 对于大多数的函数都是有集成的很紧密,特别是 C 语言中没有的 C++ 中的 API 是对

十分愚蠢的错误记录·······(C++创建对象时new的问题)

时光毁灭记忆、已成空白 提交于 2019-12-05 21:20:39
今天C++上机课啊,就是要写个小项目实现一下二叉搜索树及其各种方法。结果在创建对象上挂掉了····回头看才发现多么弱智····现记录下来,希望永不再犯。 一共就两个类,BST类代表整颗树,里面有个根节点root,和储存结点的vector容器;另一个TreeNode类,代表树叶结点,结点数据是单独的一个int。 以下是大错特错的构造函数: 1 BST::BST() { 2 L = {22,15,60,3,25,11,50,1,27,25,49,40,53,30,19,11}; 3 for (auto it = L.begin(); it != L.end(); it++) { 4 treeVec.push_back(&TreeNode(*it)); 5 } 6 } 第四行其实根本没有创建对象······断点调试可以发现每个对象被创建后又被马上调用析构函数销毁了。为什么呢,因为这里根本没有分配内存····· 参考: https://blog.csdn.net/qq_18884827/article/details/52334303 : c++里面, 创建对象, ClassName object(初始化参数);在Stack栈里面分配空间,自动释放。或者用 ClassName object=new ClassNam();在heap堆里面分配空间,要手动释放。再看:https://blog

基于数组构造的程序设计

帅比萌擦擦* 提交于 2019-12-05 15:22:42
1、调用相关函数实现将一组double型数据的小数部分之和输出到屏幕上。 #include<iostream> using namespace std; #define M 5 void PrintData(double sum); void ReadData(double tt[M]); double Acc(int k, double dd[]) {//实现计算数组元素的小数部分之和 //写入你的代码 double sm = 0.0; for (int k = 0; k < M; k++) { sm += dd[k] - (int)dd[k]; } return sm; } void PrintData(double sum) { //把sum数据输出到屏幕上 //写入你的代码 cout << sum; } void ReadData(double tt[M]) { //从键盘中输入5个double数据存于tt数据中 //写入你的代码 for (int i = 0; i < M; i++) { cin >> tt[i]; } } void main() { int m = 0; double sm = 0.0; double tt[M]; system("cls");//清除屏幕数据 ReadData(tt); //读取数据 sm = Acc(m, tt); /

类与指针

元气小坏坏 提交于 2019-12-05 09:43:33
析构函数构造的两种方法: range::range (float a ,float b,float c){width=a,length=b,hight=c; cout<<"构数成功造函"<<endl;} 这种方法写出时,函数内部的顺序没有关系。 2、 range::range(float a,float b,float c) {width=a,length=b,hight=c,cout<<"构造析构函数成功"<<endl;} eg: class A { public : // 构造和析构必须public A( ) { cout<<"构造 A()"<< endl; } ~A( ) { cout<<"析构~A()"<< endl; } }; class B { public : B( ) { cout<<"构造 B()"<<endl; } ~B( ) { cout<<"析构~B()"<<endl; } }; 构造函数遵从:先构造,后析构 后构造,先析构 *** 构造对象数组: 每个元素都是一个对象 数组有多少个对象就调用多少次构造函数 代码块: class range { float width; float length; float hight; float area; int x; public: range::range(float a,float b,float c)