• 比较显式调用构造函数和析构函数


    1.首先看如下的代码,显式调用析构函数:

     C++ Code 
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
     
    #include <iostream>
    using namespace std;

    class MyClass
    {
    public:
        MyClass()
        {
            n_ = 1;
            cout << "Constructors" << endl;
        }
        ~MyClass()
        {
            cout << "Destructors" << endl;
        }
        void display()
        {
            cout << n_ << endl;
        }
    private:
        int n_;
    };

    int main (void)
    {
        MyClass *pMyClass = new MyClass;
        pMyClass->~MyClass();
        delete pMyClass;
        return 0;
    }

    输出为:

    Constructors

    Destructors

    Destructors


    证实了一些说法:

    new的时候,其实做了两件事,

    一是:调用malloc分配所需内存(实际上是调用operator new),二是:调用构造函数。

    delete的时候,也是做了两件事,

    一是:调用析造函数,二是:调用free释放内存(实际上是调用operator delete)。

    这里只是为了演示,正常情况下析构函数只会被调用一次,如果被调用两次,而析构函数内有delete的操作,会导致内存释放两次的错误。

    2. 接着再看:显式调用构造函数(第一种方式):

     C++ Code 
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
     
    #include <iostream>

    using namespace std;

    class MyClass
    {

    public:

        MyClass()
        {
            n_ = 1;

            cout << "Constructors" << endl;
        }

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

        void display()
        {
            cout << "n=" << n_ << endl;
        }

    private:

        int n_;

    };



    int main (void)
    {

        MyClass *pMyClass = (MyClass *)malloc(sizeof(MyClass));

        pMyClass->MyClass::MyClass(); //第一种方式

        pMyClass->display();

        free(pMyClass); // 不能用delete,对应malloc,不会调用析构函数

        return 0;
    }

    输出为:

    Constructors

    n=1


    3.显示调用构造函数(第二种方式):placement new

     C++ Code 
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
     
    #include <iostream>

    using namespace std;

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

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

        void display()
        {
            cout << "n=" << n_ << endl;
        }

    private:

        int n_;
    };

    int main (void)
    {
        char tmp[10];
        MyClass *pMyClass = new (tmp) MyClass; // placement new 用法
        pMyClass->display();
        pMyClass->~MyClass(); // 不是堆上的内存,不能用delete 
        return 0;
    }

    Constructors

    n=1

    Destructors
    placement new的作用就是:创建对象(调用该类的构造函数)但是不分配内存,而是在已有的内存块上面创建对象。用于需要反复创建并删除的对象上,可以降低分配释放内存的性能消耗。

    显式调用构造函数和析构函数

    今天跟同事聊天,他说到STL源码有用到显示调用析构函数。试一了一下。果然能行。

    复制代码
    #include <iostream>
    usingnamespace std;

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

    };

    int _tmain(int argc, _TCHAR* argv[])
    {
    MyClass* pMyClass =new MyClass;
    pMyClass->~MyClass();
    delete pMyClass;

    }
    复制代码

    结果:

    Constructors

    Destructors        //这个是显示调用的析构函数

    Destructors        // 这个是delete调用的析构函数

    这有什么用?

    有时候,在对象的生命周期结束前,想先结束这个对象的时候就会派上用场了。

    由此想到的:

    因为我知道。

    new的时候,其实做了两件事,一是:调用malloc分配所需内存,二是:调用构造函数。

    delete的时候,也是做了两件事,一是:调用析造函数,二是:调用free释放内存。

    所以推测构造函数也是可以显式调用的。做了个实验。

    int _tmain(int argc, _TCHAR* argv[])
    {
    MyClass* pMyClass = (MyClass*)malloc(sizeof(MyClass));
    pMyClass->MyClass();
    //
    }

    编译pMyClass->MyClass()出错:

    error C2273: 'function-style cast' : illegal as right side of '->'operator

    天啊,它以为MyClass是这个类型。

    解决办法有两个:

    第一:pMyClass->MyClass::MyClass();
    第二:new(pMyClass)MyClass();

    第二种用法涉及C++ placement new 的用法

    placement new的作用就是:创建对象(调用该类的构造函数)但是不分配内存,而是在已有的内存块上面创建对象。用于需要反复创建并删除的对象上,可以降低分配释放内存的性能消耗。请查阅placement new相关资料。

    显示调用构造函数有什么用?

    有时候,你可能由于效率考虑要用到malloc去给类对象分配内存,因为malloc是不调用构造函数的,所以这个时候会派上用场了。

    另外下面也是可以的,虽然内置类型没有构造函数。

    int* i = (int*)malloc(sizeof(int));
    new (i) int();

    感觉这些奇奇怪怪的用法最好在写代码库时,为了达到某个目时去使用,不推荐应用开发时使用。

  • 相关阅读:
    Python-HTML基础
    异常处理
    反射hasattr; getattr; setattr; delattr
    Python 属性方法、类方法、静态方法、 特殊属性__doc__ (内建属性)
    Python3 day6面向对象
    re模块计算器作业
    re正则表达式:import re ;re.search()
    hashlib模块学习:hmac
    ConfigParser模块,主要应用于对php.ini等格式的配置文件内容读取和生成。删改较少用
    ymal文档格式 处理
  • 原文地址:https://www.cnblogs.com/alantu2018/p/8470894.html
Copyright © 2020-2023  润新知