`
clskkk2222
  • 浏览: 34892 次
  • 性别: Icon_minigender_1
  • 来自: 南京
社区版块
存档分类
最新评论
  • NeuronR: 引用因为用于向函数传递对象和从函数返回对象,该构造函数一般不应 ...
    复制构造函数

析构函数 管理指针成员

    博客分类:
  • C++
阅读更多

析构函数就是这样的一个特殊函数,它可以完成所需的资源回收,作为类构造函数的补充撤销类对象

时会自动调用析构函数

 

动态分配的对象只有在指向该对象的指针被删除时才撤销

 

当对象的引用或指针超出作用域时,不会运行析构函数,只有删除指向动态分配对象的指针或实际对

象(而不是对象的引用)超出作用域时,才会运行析构函数

 

撤销一个容器(不管是标准库容器还是内置数组)时,也会运行容器中的类类型元素的析构函数


容器中的元素总是按逆序撤销:首先撤销下标为 size() - 1 的元素,然后是下标为 size() - 2 的

元素……直到最后撤销下标为 [0] 的元素

 

析构函数通常用于释放在构造函数或在对象生命期内获取的资源


如果类需要析构函数,则它也需要赋值操作符和复制构造函数,这是一个有用的经验法则,这个规则

常称为三法则,指的是如果需要析构函数,则需要所有这三个复制控制成员

 

析构函数并不仅限于用来释放资源,一般而言,析构函数可以执行任意操作,该操作是类设计者希望

在该类对象的使用完毕之后执行的

 

与复制构造函数或赋值操作符不同,编译器总是会为我们合成一个析构函数

 

合成析构函数按对象创建时的逆序撤销每个非 static 成员,因此,它按成员在类中声明次序的逆序

撤销成员,对于类类型的每个成员,合成析构函数调用该成员的析构函数来撤销对象

 

撤销内置类型成员或复合类型的成员没什么影响,尤其是,合成析构函数并不删除指针成员所指向的

对象

 

析构函数是个成员函数,它的名字是在类名字之前加上一个代字号(~),它没有返回值,没有形参

,因为不能指定任何形参,所以不能重载析构函数,虽然可以为一个类定义多个构造函数,但只能提

供一个析构函数,应用于类的所有对象

 

析构函数与复制构造函数或赋值操作符之间的一个重要区别是,即使我们编写了自己的析构函数,合

成析构函数仍然运行

 

包含指针的类需要特别注意复制控制,原因是复制指针时只复制指针中的地址,而不会复制指针指向

的对象

 

大多数 C++ 类采用以下三种方法之一管理指针成员:
1. 指针成员采取常规指针型行为。这样的类具有指针的所有缺陷但无需特殊的复制控制
2. 类可以实现所谓的“智能指针”行为,指针所指向的对象是共享的,但类能够防止悬垂指针
3. 类采取值型行为,指针所指向的对象是唯一的,由每个类对象独立管理

 

具有指针成员且使用默认合成复制构造函数的类具有普通指针的所有缺陷,尤其是,类本身无法避免

悬垂指针

 

建议:管理指针成员
具有指针成员的对象一般需要定义复制控制成员,如果依赖合成版本,会给类的用户增加负担,用户

必须保证成员所指向的对象存在,只要还有对象指向该对象

 

为了管理具有指针成员的类,必须定义三个复制控制成员:复制构造函数、赋值操作符和析构函数。

这些成员可以定义指针成员的指针型行为或值型行为

 

#include <iostream>
#include <string>
#include <vector>
using namespace std;

class Apple{
    int i;    
public:
    Apple(int n):i(n){}
    ~Apple(){
        cout << "Aapple No." << i << " destructed" << endl;       
    }  
}; 


// class that has a pointer member that behaves like a plain pointer
class HasPtr {
public:
    // copy of the values we're given
    HasPtr(int *p, int i): ptr(p), val(i) { }
    
    // const members to return the value of the indicated data member
    int *get_ptr() const { return ptr; }
    int get_int() const { return val; }
    
    // non const members to change the indicated data member
    void set_ptr(int *p) { ptr = p; }
    void set_int(int i) { val = i; }
    
    // return or change the value pointed to, so ok for const objects
    int get_ptr_val() const { return *ptr; }
    void set_ptr_val(int val) const { *ptr = val; }

private:
    int *ptr;
    int val;
};


int main()
{
    Apple a(0);   // 
    
    {             // new scope
        Apple a1(1);
    }             //exit local scope; destructor called on a1
    
    Apple *a2 = 0;
    {
        a2 = new Apple(2);
    }             //thouth exit local scope ,destructor not called 
    cout << "Apple a2 still exist " << endl;
    delete a2;    //ok  destructor called on a2
    
    cout << "===========================" << endl; 
    Apple a3(3);
    Apple a4(4);
    Apple a5(5);
    {
          Apple as[3] = {a3,a4,a5};  
    }             //destruct order: a5 a4 a3
    
    int obj = 0;
    HasPtr ptr1(&obj, 42); // int* member points to obj, val is 42
    HasPtr ptr2(ptr1);     // int* member points to obj, val is 42

    ptr1.set_int(0); // changes val member only in ptr1
    cout << ptr2.get_int() << endl;  // returns 42
    cout << ptr1.get_int() << endl;  // returns 0

    ptr1.set_ptr_val(42); // sets object to which both ptr1 and ptr2 point
    cout << ptr2.get_ptr_val() << endl;   // returns 42

    int *ip = new int(42); // dynamically allocated int initialized to 42
    HasPtr ptr(ip, 10);    // Has Ptr points to same object as ip does
    delete ip;             // object pointed to by ip is freed
    ptr.set_ptr_val(0);    // disaster: The object to which Has Ptr points was freed!
    cout << ptr.get_ptr_val() << endl;

    int i = 42;
    HasPtr p1(&i, 42);
    HasPtr p2 = p1;
    cout << p2.get_ptr_val() << endl;
    p1.set_ptr_val(0);
    cout << p2.get_ptr_val() << endl;
     
    return 0;   
}

 

 

 

 

0
0
分享到:
评论

相关推荐

    虚析构函数示例

    析构函数是C++中的一个特殊成员函数,其作用是在对象生命周期结束时自动调用,用于清理对象占用的资源,如释放内存或关闭文件等。析构函数的名称以波浪线(~)开头,后面跟类的名字。 虚析构函数(virtual ...

    深析C++析构函数

    析构函数是在对象生命周期结束时(如对象离开作用域或显式删除动态分配的对象)自动调用的一个特殊成员函数。其主要任务是释放对象所占用的资源,例如动态分配的内存。 **语法:** ```cpp ~ClassName() { // 释放...

    delphi析构函数的使用

    在这个阶段,析构函数会按逆序调用对象成员变量的析构函数,然后执行自定义的清理代码。例如,如果你的对象动态创建了其他对象,你应该在析构函数中释放这些子对象。 ```delphi type TMyClass = class private ...

    C++ 析构函数 参考源代码

    在C++编程语言中,析构函数是一种特殊类型的成员函数,它的主要职责是释放对象在创建过程中分配的资源。当你创建一个类,并为类的对象分配内存时,可能会涉及到动态内存分配或其他需要清理的工作,比如关闭文件、...

    C++析构函数使用virtual的原因

    类型拥有指针成员或引用成员时,通常需要实现析构函数来管理这些资源。如果这些类型还涉及多态,即作为其他类的基类,那么为了确保资源的正确释放,基类的析构函数应当声明为虚函数。 3. **一致性原则** 如果一个...

    C++中析构函数定义成虚函数的原因.doc

    - **析构函数**:在C++中,析构函数是一种特殊的成员函数,用于在对象生命周期结束时释放资源或执行必要的清理工作。析构函数在对象销毁前自动调用。 - **虚函数**:虚函数允许派生类重写基类中的同名函数,从而实现...

    派生的析构函数被调用

    在C++编程中,析构函数是一个特殊类型的成员函数,用于清理对象在创建时分配的资源。当对象的生命周期结束时,析构函数会被自动调用。标题“派生的析构函数被调用”涉及的是面向对象编程中的继承概念,特别是在多态...

    析构函数不能抛出异常的原因

    这样,在对象销毁时,智能指针会自动释放所管理的资源,而无需在析构函数中显式地进行资源释放操作。 - **资源获取即初始化(RAII)**:采用RAII技术,可以在构造函数中获取资源,并在析构函数中释放资源。这种方法...

    C++箴言:避免析构函数调用虚函数

    - **使用智能指针**:利用智能指针(如`std::unique_ptr`或`std::shared_ptr`)来管理对象的生命周期,这样就不需要手动编写析构函数。 总之,在C++中遵循“避免在析构函数中调用虚函数”的原则非常重要。这不仅...

    C++析构函数 快速学习

    这些智能指针在自身析构时会自动调用所持有的对象的析构函数,简化了内存管理。 当涉及到嵌套对象或者对象间的相互依赖时,析构函数的顺序也很关键。通常,成员对象的析构函数会在包含它的对象的析构函数之后调用,...

    实验1_析构函数_

    在实际编程过程中,还可以使用智能指针(如`std::unique_ptr`和`std::shared_ptr`)来自动管理动态内存,这样就不需要手动编写析构函数来释放内存。然而,理解析构函数的工作原理仍然是掌握C++内存管理的关键一步。 ...

    当析构函数遇到多线程

    `shared_ptr`是一种智能指针,它能够自动管理对象的引用计数,当最后一个`shared_ptr`实例被销毁时,它会自动调用对象的析构函数。这意味着,只要存在指向一个对象的`shared_ptr`实例,该对象就不会被析构,从而解决...

    《当析构函数遇到多线程》PPT

    这些智能指针不仅能够管理对象的生命周期,还能帮助解决多线程环境下的析构函数问题。 **shared_ptr的作用**: - **引用计数**:`shared_ptr`通过引用计数机制跟踪指向同一对象的所有`shared_ptr`实例的数量。 - **...

    构造、析构函数

    构造函数与析构函数是C++中非常重要的概念,它们在对象的生命周期管理中扮演着核心角色。构造函数主要用于初始化对象,而析构函数则负责清理对象占用的资源。 #### 构造函数 构造函数是一种特殊的成员函数,其名称...

    C++箴言:防止异常离开析构函数

    2. **使用智能指针**:通过使用智能指针(如 `std::unique_ptr` 或 `std::shared_ptr`),可以自动管理资源的生命周期,从而减少在析构函数中显式释放资源的需求。 3. **资源池技术**:如果必须要在析构函数中释放...

    DTLib.zip_1FW6_dtlib_sittinge6u_自动调用析构函数

    总的来说,这个代码可能演示了如何在C++中利用虚析构函数确保在继承体系中正确调用析构函数,以及可能使用智能指针来管理对象生命周期的实践。通过对这些关键知识点的理解,你可以有效地阅读和理解`DTLib.zip`中的源...

    关于 析构函数 的问题

    析构函数是一种特殊的成员函数,其名称与类名相同,但在前面加上波浪线`~`。当一个对象生命周期结束时,例如对象作用域结束或显式删除对象,析构函数会被自动调用。其主要任务是释放对象占用的资源,确保程序的稳定...

    构造函数与析构函数_构造函数ppt_

    析构函数是在对象生命周期结束时(通常是对象的作用域结束或显式删除指针对象时)自动调用的一个特殊方法,用于清理和释放对象可能占用的资源。析构函数的名称以波浪线`~`开头,后面跟着类名,且无返回值。例如: `...

Global site tag (gtag.js) - Google Analytics