精华内容
下载资源
问答
  • 对同一类进行两次析构的问题

    千次阅读 2014-09-17 19:52:16
    对于一个类进行两次析构一般情况不会出现任何wenti

    对于同一个类进行两次析构一般情况不会出现问题,但是当在析构函数中调用了delete对于类中的成员变量进行销毁则会出现问题,如果进行两次析构函数,则会对同一个变量进行两次销毁,则第二次销毁就会出现问题,会出现_BLOCK_TYPE_IS_VALID(pHead->nBlockUse的问题。

    出现这个问题的原因有:

    1.内存泄漏:所以当程序退出是,系统会收回分配的内存,于是调析构函数,由于内存已被错误地释放,于是就会出现“Debug Assertion Failed”的错误。

    2.这个assert说明什么问题,说明有一块内存在被释放的时候,它的头部里面的信息已经被改掉了,和预期的不一样,内存分配的程序往往在被分配出的内存块头部放上一些校验信息,这个信息内存的用户是不知道也不应该修改的。这样,在内存被释放的时候,内存分配程序就可以校验出这个头部信息是否被改过了,若被改过,就说明发生了内存的corruption。

    这种corruption有两种可能:

    1.说明有人在内存越界写东西;

    2.这块内存已经被释放了,又被重复释放了一次。

     3.pHead->nBlockUse已经是空指针了。或者它指向的东西已经消失了。

    下列是一个例子:

    class A
    {
    public:
    	A()
    	{
    		use = new int[5];
    	}
    	~A()
    	{
    		delete[] use;
    	}
    private:
    	int *use;
    };
    
    class B
    {
    public:
    	B(A &obj) :a(obj)
    	{
    
    	}
    	~B()
    	{}
    private:
    	A a;
    };
    
    int main()
    {
        A a;
        B b(a);
        return 0;
    }
    
    这个例子会发生错误,因为在B进行析构的时候会对成员A进行析构,会销毁a的变量use,之后会再对A进行一次析构,这样同一个类对象a就进行了两次析构,要消除这种错误,只有对B的成员变量a定义为A的引用,如下面的例子所所示。
    class A
    {
    public:
    	A()
    	{
    		use = new int[5];
    	}
    	~A()
    	{
    		delete[] use;
    	}
    private:
    	int *use;
    };
    
    class B
    {
    public:
    	B(A &obj) :a(obj)
    	{
    
    	}
    	~B()
    	{}
    private:
    	A& a;
    };
    


    展开全文
  • (2)当一个类中含有对象成员时,在启动本类的构造函数之前,先分配对象空间,按对象成员的声明顺序执行他们各自的构造函数,再继续执行本类的构造函数; (3)对于非静态的局部对象,他们的析构函数的执行顺序与...

    首先,我们来看一段代码:

    #include<iostream>
    using namespace std;
    
    class A
    {
    public:
    	A()
    	{
    		cout << "A's constructor." << endl;
    	}
    	~A()
    	{
    		cout << "A's destructor." << endl;
    	}
    };
    
    class B
    {
    public:
    	B()
    	{
    		cout << "B's constructor." << endl;
    	}
    	~B()
    	{
    		cout << "B's destructor." << endl;
    	}
    };
    
    class C
    {
    private:
    	B bInC;
    public:
    	C()
    	{
    		cout << "C's constructor." << endl;
    	}
    	~C()
    	{
    		cout << "C's destructor." << endl;
    	}
    	A aInC;
    };
    
    class D:public C
    {
    public:
    	D()
    	{
    		cout << "D's constructor." << endl;
    	}
    	~D()
    	{
    		cout << "D's destructor." << endl;
    	}
    	A aInD;
    private:
    	B bInD;
    };
    
    int main(void) {
    	D d;
    	return 0;
    }

    那么,这段程序执行后,输出什么呢?

    B's constructor.
    A's constructor.
    C's constructor.
    A's constructor.
    B's constructor.
    D's constructor.
    D's destructor.
    B's destructor.
    A's destructor.
    C's destructor.
    A's destructor.
    B's destructor.

    分析如下:

    (1)存在继承关系时,先执行父类的构造函数,再执行子类的构造函数;

    (2)当一个类中含有对象成员时,在启动本类的构造函数之前,先分配对象空间,按对象成员的声明顺序执行他们各自的构造函数,再继续执行本类的构造函数;

    (3)对于非静态的局部对象,他们的析构函数的执行顺序与构造函数相反。

    在本程序中:

    (1)执行main(),需要创建一个对象d,所以,需要执行D的构造函数。而D继承自C,所以先要执行C的构造函数;

    (2)而在C中存在对象成员bInC和aInC,所以,在C的构造函数执行之前,先按声明顺序执行B和A的构造函数,然后执行C的构造函数;

    (3)轮到构造d了,但是D中有对象成员aInD和bInD,所以,在D的构造函数执行之前,先按声明顺序执行A和B的构造函数,最后,执行D的构造函数;

    (4)以上所有对象的析构函数以与构造函数的执行顺序相反的顺序执行。

    最终的执行结果就不言而喻了。

    学无止境,共同学习。若本文所述存在错误或不妥之处,欢迎指正~

    展开全文
  • 对于全局变量或静态变量,在析构函数里面释放资源有的时候会确实有点不好,万一你的析构里面的代码依赖外部的某些资源,而这些资源优先于你的资源被释放了,那么当你的资源呗释放的时候就会崩溃了。。。呵呵。今天...

    把所有的资源释放的工作放在析构里面是危险的,除非你的类是个生命期局部的类。

    对于全局变量或静态变量,在析构函数里面释放资源有的时候会确实有点不好,万一你的析构里面的代码依赖外部的某些资源,而这些资源优先于你的资源被释放了,那么当你的资源呗释放的时候就会崩溃了。。。呵呵。

    今天遇到了 在析构里 delete fnt;出现的问题即是如此。hge引擎已经被事先释放了。

    看来,为全局、静态、单件实例的类提供一个Release接口是非常必要的。让其在析构里面什么也不做。

    展开全文
  • 从语法上来讲,一个函数被声明为protected或者private,那么这个函数就不能从“外部”直接被调用了。 对于protected函数,子类“内部”其他函数可以调用之。 而对于private函数,只能被本“内部”其他...

    引用百度用户:jeny_man的回答

    你提出这个问题,说明你已经对c++有所思考了。
    从语法上来讲,一个函数被声明为protected或者private,那么这个函数就不能从“外部”直接被调用了。
    对于protected的函数,子类的“内部”的其他函数可以调用之。 而对于private的函数,只能被本类“内部”的其他函数说调用。
    语法上就是这么规定的,你肯定也知道的咯。 那么为什么有时候将构造函数或者析构函数声明为protected的或者private的?
    通常使用的场景如下:
    1。如果你不想让外面的用户直接构造一个类(假设这个类的名字为A)的对象,而希望用户只能构造这个类A的子类,那你就可以将类A的构造函数/析构函数声明为protected,而将类A的子类的构造函数/析构函数声明为public。例如:
    class A { protected: A(){} public: … }; calss B : public A {
    public: B(){} … }; A a; // error B b; // ok
    2. 如果将构造函数/析构函数声明为private,那只能这个类的“内部”的函数才能构造这个类的对象了。这里所说的“内部”不知道你是否能明白,下面举个例子吧。
    class A { private: A(){ } ~A(){ } public: void Instance()//类A的内部的一个函数
    { A a; } };
    上面的代码是能通过编译的。上面代码里的Instance函数就是类A的内部的一个函数。Instance函数体里就构建了一个A的对象。
    但是,这个Instance函数还是不能够被外面调用的。为什么呢?
    如果要调用Instance函数,必须有一个对象被构造出来。但是构造函数被声明为private的了。外部不能直接构造一个对象出来。 A
    aObj; // 编译通不过 aObj.Instance();
    但是,如果Instance是一个static静态函数的话,就可以不需要通过一个对象,而可以直接被调用。如下:class A {
    private: A():data(10){ cout << “A” << endl; } ~A(){ cout << “~A” <<
    endl; } public: static A& Instance() { static A a; return a; } void
    Print() { cout << data << endl; } private: int data; }; A& ra =
    A::Instance(); ra.Print(); 上面的代码其实是设计模式singleton模式的一个简单的C++代码实现。
    还有一个情况是:通常将拷贝构造函数和operator=(赋值操作符重载)声明成private,但是没有实现体。
    这个的目的是禁止一个类的外部用户对这个类的对象进行复制动作。 细节请看《effective
    C++》里面的一个条款。具体哪个条款不记得了。你自己去找吧。

    展开全文
  • 、构造函数和析构函数的由来类的数据成员不能在类的声明时候初始化,为了解决这问题? 使用构造函数处理对对象的初始化。构造函数是种特殊的成员函数,与其他函数不同,不需要用户调用它,而是创建对象的时候自动...
  • 基类虚析构的意义

    2021-01-21 18:35:29
    对于一般的类,并不要求将其虚构函数写成虚析构,因为当用“virtual”关键字修饰一个函数时,系统默认为该类维护(创建)一个虚表(装有虚函数地址的一维数组),创建该类的对象时,取对象内存单元的前四个字节,...
  • 创建一个派生类对象的时候,首先调用基类的构造函数,再调用派生类的构造函数。对于析构函数,则先释放派生类再释放基类。 例子: #include &lt;iostream&gt; #include &lt;string&gt; using ...
  • 对于一个给定,有且只有一个析构函数。 2、析构函数组成:一个函数体+一个析构部分(implicit);所完成工作:先执行函数体,然后按照初始化成员逆序销毁成员。在这里需要注意是销毁成员并不是函数体...
  • 读《高质量程序设计指南》chapter 14总结 一般情况下,对于任意一个类A,如果不显示声明和定义,会自动生成默认4个public inline函数 class A { A(); //////////构造函数
  • 构造函数、析构函数与赋值函数是每个类最基本函数。...对于任意一个类A,如果不想编写上述函数,C++编译器将自动为A产生四个缺省函数(也只是在需要时候才会产生),如 A(void); // 缺省无参数
  • 对于任一的一个类A,如果不想编写上述函数,C++编译器就会自动产生四个缺省函数。例如: A(void); //缺省无参构造函数 A(const A &a); //缺省拷贝构造函数 ~A(void); //缺省析构函数 A&
  • 构造函数、析构函数与赋值函数是每个类最基本函数。...对于任意一个类A,如果不想编写上述函数,C++编译器将自动为A产生四个缺省函数(也只是在需要时候才会产生),如 A(void); // 缺省无参数构...
  • 创建一个新类时,这个类和现有类相似(只是多出一些变量或函数时候)例如:同样是车例子,我先有一个类,然后要定义一个轿车类,发现轿车和车有相似(都是四个轮子,都是用方向盘等等) 当你创建多
  • 大家都知道,当程序中创建一个类指针对象并将其初始化时候,只要该类有指针成员变量,且在构造函数中利用new操作符为该指针变量分配堆块上内存时,我们就需要实时注意需要手动管理该段内存释放。函数中用de
  • 为了理解构造函数和析构函数,先说明一下同一个类的对象之间的不同之处:首先,对象名不相同。其次,对象的数据成员的值不相同。我们在声明一个对象时,可以对其初始化。如果对其初始化,那么程序会向操作系统申请为...
  • 14.1 类的初始化 型如下面这样的类:Class data{Public: int inval; char* ptr;...对于大多数类而言,提供一个构造函数初始化数据成员是一个好的选择。但是上面的初始化形式在 初始化大型数据结构,如调
  • 第一次学习C++ CLass时仅对构造器和析构器有了一个初步认识,“构造器在创建对象时被自动调用,用来初始化对象中成员;析构器在销毁对象时被自动调用,用于完成清理工作”,但这个还是停留在表面,比较浅显,...
  • 翻开收藏夹,好多好多,让人看完不知道该怎么下手,也意识到必须来更新博客了,同时领悟到在项目时候,一个文档,可以零星记录问题始终,在结项时候,利用几天偷闲时光,整理整理,对于领悟与回味,甚好。...
  • C++ 构造与析构

    2018-10-31 17:11:25
    1.养成一个习惯,只要是变量,定义后要初始化 2.在C++当中要完成对象初始化工作,可以借助构造来完成,如果要完成对象清理操作,借助析构来完成 3.在C++里面对于对象初始化有4种方式: 1、直接赋值(结构...
  • effective c++:virtual函数在构造...对于一个类,如果你没有声明,c++会自动生成一个构造函数,一个析构函数,一个copy构造函数和一个copy assignment操作符。 class Empty { public:  Empty() { ... } //...
  • C++ 构造和析构函数

    2020-08-03 10:25:21
    构造函数 构造函数是一种特殊类成员函数 创建类对象时使用 名称与类名相同 无返回值 ...如果编译器支持c++11则可以使用列表初始化 ...接受一个参数构造函数允许使用赋值语法将对象初始化为...每个类只能有一个析构
  • 魔法方法——构造与析构 ...主要用来重新修改和对于实际类()里面所带参数的修改,__new__ 方法主要任务是返回一个实例对象,通常是参数 cls 这个类的实例化对象,当然你也可以返回其他对象。 3、_...
  • 来说,都是用一个已有对象去创建构造一个对象。 当对象中含有指针或作为数据成员对于已有对象在构造出新对象后,仍需要对该已有对象进行引用或利用,需要我们自己定义拷贝构造函数(进行深...
  • C++ 构造/析构/赋值/拷贝函数比较 构造函数、析构函数与赋值函数是每个类最基本函数。每个类只有一个析构函数,但...对于任意一个类A,如果不想编写上述函数,C++编译器将自动为A产生四个缺省函数,如A(void); //
  •  C++中构造函数是一个同名,没有返回值特殊函数,主要是构造对象,为对象分配资源,由于没有返回值,如何判断构造对象过程一定成功呢?  答:参考链接C++构造函数中抛出异常 C++中通知对象构造失败...
  • 对象初始化,拷贝和析构

    千次阅读 2015-05-15 22:10:41
    对于一个类,如果程序员不显式声明定义上述函数,编译器自动产生4个inline函数, A();A(const A& );~A(); A& operator=(const A& ) 1.不要在构造函数内做与初始化无关工作,不要在析构函数内做与销毁...
  •  构造函数与类同名我们以此来标识构造函数为了声明一个缺省构造函数,构造函数上惟一语法限制是它不能指定返回类型甚至void 也不行,C++语言对于一个类可以声明多少个构造函数没有限制,只要每个构造函数参数...
  • C++ 构造/析构/赋值/拷贝函数比较 1....对于任意一个类A,如果不想编写上述函数,C++编译器将自动为A产生四个缺省函数,如 A(void); // 缺省无参数构造函数 A(const A &a); 
  • 在面试过程中,如果要让写一个string类的模拟,那么,面试官多半是想考你关于深浅拷贝的某些知识。  对于string类的实现来说,比较重要的几个成员函数,也就是构造函数、析构函数、拷贝构造函数、赋值运算符重载...

空空如也

空空如也

1 2 3 4 5 ... 16
收藏数 301
精华内容 120
关键字:

对于一个类的析构