基础学习:构造函数和析构函数程序员进阶笔记

1.  构造函数用来对类对象进行初始化,它完成对内存空间的申请、赋初值等工作。  2.  析构函数主要是用来做清理工作的。

补充:函数名或变量名前面有"::"但是没有类名,说明这是全局变量或公共函数,并且不属于任何命名空间。仅此而已。

1、构造函数和析构函数为什么没有返回值? 构造函数和析构函数是两个非常特殊的函数:它们没有返回值。这与返回值为void的函数显然不同,后者虽然也不返回任何值,但还可以让它做点别的事情,而构造函数和析构函数则不允许。在程序中创建和消除一个对象的行为非常特殊,就像出生和死亡,而且总是由编译器来调用这些函数以确保它们被执行。如果它们有返回值,要么编译器必须知道如何处理返回值,要么就只能由客户程序员自己来显式的调用构造函数与析构函数,这样一来,安全性就被人破坏了。另外,析构函数不带任何参数,因为析构不需任何选项。如果允许构造函数有返回值,在某此情况下,会引起歧义。如下两个例子class C{public: C(): x(0) { } C(int i): x(i) { }

private: int x;};

如果C的构造函数可以有返回值,比如int:int C():x(0) { return 1; } //1表示构造成功,0表示失败那么下列代码会发生什么事呢?C c = C();  //此时c.x == 1!!!很明显,C()调用了C的无参数构造函数。该构造函数返回int值1。恰好C有一个但参数构造函数C(int i)。于是,混乱来了。按照C++的规定,C c = C();是用默认构造函数创建一个临时对象,并用这个临时对象初始化c。此时,c.x的值应该是0。但是,如果C::C()有返回值,并且返回了1(为了表示成功),则C++会用1去初始化c,即调用但参数构造函数C::C(int i)。得到的c.x便会是1。于是,语义产生了歧义。使得C++原本已经非常复杂的语法,进一步混乱不堪。构造函数的调用之所以不设返回值,是因为构造函数的特殊性决定的。从基本语义角度来讲,构造函数返回的应当是所构造的对象。否则,我们将无法使用临时对象:void f(int a) {...}  //(1)void f(const C& a) {...} //(2)f(C()); //(3),究竟调用谁?对于(3),我们希望调用的是(2),但如果C::C()有int类型的返回值,那么究竟是调(1)好呢,还是调用(2)好呢。于是,我们的重载体系,乃至整个的语法体系都会崩溃。这里的核心是表达式的类型。目前,表达式C()的类型是类C。但如果C::C()有返回类型R,那么表达式C()的类型应当是R,而不是C,于是便会引发上述的类型问题。

2、显式调用构造函数和析构函数#include <iostream>using namespace std;

class MyClass{public: MyClass() { cout << "Constructors" << endl; }

~MyClass() { cout << "Destructors" << endl; }};

int main(){ MyClass *pMyClass = new MyClass; pMyClass->~MyClass(); delete pMyClass;

return 0;}

int main(){ S s1(2); S s2(s1); return 0;}

当给s2初始化的时候调用了s2的拷贝构造函数,由于是值传递,系统会给形参st重新申请一段空间,然后调用自身的拷贝构造函数把s1的数据成员的值传给st。当调用自身的拷贝构造函数的时候又因为是值传递,所以...也就是说,只要调用拷贝构造函数,就会重新申请一段空间,只要重新申请一段空间,就会调用拷贝构造函数,这样一直下去就形成了一个死循环。所以拷贝构造函数一定不能是值传递。 4、构造函数/析构函数抛出异常的问题构造函数抛出异常:    1.不建议在构造函数中抛出异常;    2.构造函数抛出异常时,析构函数将不会被执行;C++仅仅能删除被完全构造的对象(fully contructed objects),只有一个对象的构造函数完全运行完毕,这个对象才能被完全地构造。对象中的每个数据成员应该清理自己,如果构造函数抛出异常,对象的析构函数将不会运行。如果你的对象需要撤销一些已经做了的动作(如分配了内存,打开了一个文件,或者锁定了某个信号量),这些需要被撤销的动作必须被对象内部的一个数据成员记住处理。析构函数抛出异常:    在有两种情况下会调用析构函数。第一种是在正常情况下删除一个对象,例如对象超出了作用域或被显式地delete。第二种是异常传递的堆栈辗转开解(stack-unwinding)过程中,由异常处理系统删除一个对象。在上述两种情况下,调用析构函数时异常可能处于激活状态也可能没有处于激活状态。遗憾的是没有办法在析构函数内部区分出这两种情况。因此在写析构函数时你必须保守地假设有异常被激活,因为如果在一个异常被激活的同时,析构函数也抛出异常,并导致程序控制权转移到析构函数外,C++将调用terminate函数。这个函数的作用正如其名字所表示的:它终止你程序的运行,而且是立即终止,甚至连局部对象都没有被释放。概括如下:    1.析构函数不应该抛出异常;    2.当析构函数中会有一些可能发生异常时,那么就必须要把这种可能发生的异常完全封装在析构函数内部,决不能让它抛出函数之外;    3.当处理另一个异常过程中,不要从析构函数抛出异常;    在构造函数和析构函数中防止资源泄漏的好方法就是使用smart point(智能指针),C++ STL提供了类模板auto_ptr,用auto_ptr对象代替原始指针,你将不再为堆对象不能被删除而担心,即使在抛出异常时,对象也能被及时删除。因为auto_ptr的析构函数使用的是单对象形式的delete,而不是delete [],所以auto_ptr不能用于指向对象数组的指针。当复制 auto_ptr 对象或者将它的值赋给其他 auto_ptr 对象的时候,将基础对象的所有权从原来的 auto_ptr 对象转给副本,原来的 auto_ptr 对象重置为未绑定状态。因此,不能将 auto_ptrs 存储在标准库容器类型中。如果要将智能指针作为STL容器的元素,可以使用Boost库里的shared_ptr。

THE END
0.析构函数(C++)|MicrosoftLearn显式定义析构函数、复制构造函数或复制赋值运算符可防止对移动构造函数和移动赋值运算符进行隐式定义。 在这种情况下,如果复制成本高昂,未能提供移动操作通常意味着错过了优化的机会。 另请参阅 复制构造函数和复制赋值运算符 移动构造函数和移动赋值运算符 本文内容 声明析构函数 使用构造函数 破坏的顺序 显式析构函数调用 可靠编程 另请参阅 此页面是否有帮助? 是否jvzquC41fqit0vnetqyph}3eqo5{j6hp1evq1lur1fktv{zevqxt/lur
1.深入理解构造和析构函数为什么要引入构造函数和析构函数构造函数和析构函数是当你刚接触C++的时候就会碰到的两个概念,也是C++语法中较难掌握的两个概念。但是它们又是学习C++必须掌握的,可以说没有理解构造和析构函数,你的C++就还没有入门。 本文拟对构造函数、析构函数进行系统的介绍,使得那些对这两个概念有初步认识的人能有更进一步的理解。 jvzquC41dnuh0lxfp0tfv8feu9741jwvkerf1mjvckrt1@>825923
2.C++析构函数详解设计一个类时,如何写析构函数? 析构函数如果我们不写的话,C++会帮我们自动的合成一个,就是说:C++会自动的帮我们写一个析构函数。很多时候,自动生成的析构函数可以很好的工作,但是一些重要的事迹,就必须我们自己去写析构函数。 析构函数和构造函数是一对。构造函数用于创建对象,而析构函数是用来撤销对象。简单jvzquC41dnuh0lxfp0tfv8lkvj{ca<:382<328ftvkimg8igvcomu8:482845;
3.C++构造函数和析构函数(非常详细)为了完成对象的创建和销毁,C++ 中的类提供了两个特殊的函数,分别是构造函数(Constructor)和析构函数(Destructor),它们会在对象创建和销毁时会被自动调用。 C++构造函数 构造函数在对象创建时自动调用,用于完成对象的初始化工作。构造函数的使用确保了对象在被使用之前已经具备了合理的初始状态。例如,它可以为对象的属性jvzquC41e0hjcwhjgpm/pny1xkkx1~ydjm650qyon
4.C++学习——构造函数析构函数本文详细介绍了C++中构造函数和析构函数的作用、定义、使用场景,包括初始化列表、内存管理以及执行时机。构造函数用于对象创建时初始化成员变量,析构函数负责对象销毁时的清理工作。 以下内容源于C语言中文网的学习与整理,非原创,如有侵权请告知删除。 一、构造函数的详解 jvzquC41dnuh0lxfp0tfv8tssJ{Uw:7567<8:8ftvkimg8igvcomu8655:772<6
5.C++构造函数和析构函数c++构造函数和析构函数C++|构造函数和析构函数 一、构造函数 构造函数是一种特殊的成员函数,主要用于创建对象时对对象进行初始化操作,即专门用于构造新对象,并赋值对象的成员数据。 在C++ 里,构造函数的名称和类名相同,并且没有返回类型。当创建类的对象时,构造函数会自动被调用。 构造函数可以在类内也可在类外定义。 构造函数在类内的定义格式 jvzquC41dnuh0lxfp0tfv8r2a9:43@7281gsvrhng1jfvjnnu1758<5483>
6.C++超详细讲解构造函数与析构函数的用法及实现C语言上一节解决了类与对象封装的问题,这一节就是对象的初始化和清理的构造函数与析构函数的内容了;对象的初始化和清理也是两个非常重要的安全问题:一个对象或者变量没有初始状态,对其使用后果是未知,同样的使用完一个对象或变量,没有及时清理,也会造成一定的安全问题;c++利用了构造函数和析构函数解决上述问题,这两个jvzquC41yy}/lk:30pku1jwvkerf1;9;766/j}r
7.C++:构造函数和析构函数空类中真的什么都没有吗?并不是,任何类在什么都不写时,编译器会自动生成以下6个默认成员函数。 默认成员函数:用户没有显式实现,编译器会生成的成员函数称为默认成员函数。 这篇文章介绍的是构造函数和析构函数。 一,构造函数 在C语言中,我们平时在建立一个栈,或是写一些函数时,可能有时偶尔会忘记调用初始化jvzquC41dnuh0lxfp0tfv87523e89B5266:0c{ykenk0fnyckny03<=2;5778
8.c++学习——构造函数与析构函数构造函数和析构函数在c++中有2个特殊的函数:构造函数和析构函数,它们分别对类对象进行初始化和清理工作。 1. 构造函数 构造函数,与类名相同,当创建类对象时会自动调用该函数。如果创建类对象时没有手动创建构造函数,系统会自动创建一个默认的构造函数,这个默认的构造函数函数体是空的,无任何功能。 jvzquC41dnuh0lxfp0tfv8hy32817>7561gsvrhng1jfvjnnu1<9;=;8;8
9.C#构造函数和析构函数拭不去の泪痕1、构造函数和析构函数是类中比较特殊的两种成员函数,分别用来对对象进行初始化和回收对象资源。 构造函数———对象初始化!!! 析构函数———回收对象资源!! 2、对象的生命周期从构造函数开始,从析构函数结束。如果一个类含有构造函数,在实例化该类的对象时就会被调用。如果含有析构函数,则会在销毁对象时调用。jvzquC41yy}/ewgnqiy/exr1uenbpp}kcpm0r8633783;A3jvor
10.构造函数与析构函数基础,以及使用过程中的注意事项析构函数使用而C++利用了C++利用了构造函数和析构函数解决上述两个问题,这两个函数将会被编译器自动调用; 当然如果我们不提供构造和析构,编译器会提供编译器提供的构造函数与析构函数是空实现。 构造函数的意义:在创建对象时,为对象的成员属性赋值,构造函数由编译器自动调用,无需手动调用。 析构函数的意义:作用域对象小回迁系统自动调用,执行清理工作。 jvzquC41dnuh0lxfp0tfv8^N[yp0c{ykenk0fnyckny03;<;92=39
11.析构函数拷贝构造函数c++拷贝构造和析构函数本文围绕C++的构造函数和析构函数展开。构造函数用于对象初始化,可带参数、重载,有默认构造函数;析构函数在对象生命周期结束时进行清理工作。还介绍了局部、静态、全局对象的初始化,缺省构造函数,构造函数与new运算符的交互,以及拷贝构造函数等内容。 1.构造函数: jvzquC41dnuh0lxfp0tfv8r2a7?29=55;1gsvrhng1jfvjnnu1745?84;:9
12.C++最通俗易懂的构造和析构函数讲解c++构造与析构函数讲解本文深入探讨了构造函数和析构函数的概念,包括它们的定义、语法、分类及调用方式。通过具体案例,详细解析了不同类型的构造函数,如无参、有参和拷贝构造函数,以及析构函数在对象生命周期结束时的作用。 构造和析构函数 构造和析构函数的概述 构造和析构函数定义 jvzquC41dnuh0lxfp0tfv8|gkzooa=84::8138ftvkimg8igvcomu8626;;26<:
13.C++的构造函数与析构函数调用顺序饔踣晦构造函数与析构函数的基本概念 ### 构造函数与析构函数的基本概念 - 构造函数的定义与作用:初始化对象成员,分配资源。 - 析构函数的定义与作用:释放资源,清理对象。 单个类中的调用顺序 ### 单个类中的调用顺序 - 构造函数调用时机:对象创建时自动调用,顺序与声明顺序一致。 jvzquC41dnuh0lxfp0tfv8ghclysaB521cxuklqg1fkucrqu13;5:A:478