zoukankan      html  css  js  c++  java
  • C++构造与析构

    C++语言构造函数与析构函数需要注意的地方。

    构造

    考虑以下定义

    struct Node
    {
        char *name;
        int value;
        Node(char *name = "", int value = 0)
        {
            name = new char[strlen(name)+1];
            strcpy(name, name);
            value = value;
        }
    }

    声明两个对象

    Node node1("child", 10), node2(node1);

    这行语句创建了两个对象node1,node2,其中node2是用node1的成员进行初始化,现在改变node2成员值

    strcpy(node2.name, "parent");
    node2.value = 40;

    打印对象的成员值如下

    cout<<node1.name<<' '<<node1.value<<' '<<node2.name<<' '<<node2.value;

    结果如下

    parent 10 parent 40

    问题出在Node结构成员name是一个指针类型,如果结构定义中没有复制构造函数,则编译器使用默认的构造函数,此构造函数在复制值类型与复制指针类型时实现方法不同,复制指针类型时仅仅复制指针的内容(所指向的地址),所以node1和node2的name指针指向了同一个地址。

    解决这个问题的办法是自定义一个复制构造函数

    struct Node
    {
        char *name;
        int value;
        Node(char *name = "", int value = 0)
        {
            name = new char[strlen(name)+1];
            strcpy(name, name);
            value = value;
        }
        Node(const Node& node)
        {
            name = new char[strlen(node.name) + 1];
            strcpy(name, node.name);
            value = node.value;
    }            

    当然,还有一个类似的问题就是

    node2 = node1;

    这句代码也是对成员进行浅表复制,解决的办法就是自定义赋值构造函数,仅给出代码片段

    Node& operator=(const Node& node)
    {
        if(this != &n)    {    // no assignment to itself
            if(name != 0)
                delete [] name;  // 注意这里是 delete [],delete只是析构单个对象,而非字符数组
            name = new char[strlen(node.name) + 1];
            strcpy(name, node.name);
            value = node.value;
        }
        return *this;
    }

    析构

    对于以上类型的对象,因为是值类型,所以如果是作为局部变量,当对象处于作用范围之外时将被销毁,被对象占用的内存也会得到释放。然而,这个对象占用的内存虽然被释放,但是跟这个对象相关联的内存则不一定被释放。如上面这个Node类型,有一个指向string的指针成员,因此,销毁Node类型对象时,对象的指针成员(name)所占用的内存被释放(32位机器上指针占用4byte),但是指针指向的string所占用的内存将会变得无法访问,这个内存也就无法被释放了。为了避免这个问题,类(结构)定义中需要包含析构函数。析构函数在对象被销毁时自动被调用,或者主动使用delete关键字调用析构函数。析构函数不接受参数,也不返回值。

    在Node的定义增加一个析构函数

    ~Node()
    {
        if(name != 0)
            delete [] name;
    }

    以上讨论了结构(struct)的构造函数和析构函数,对于类(class)的情况类似。

  • 相关阅读:
    poj3294 Life Forms(后缀数组)
    1628. White Streaks(STL)
    1523. K-inversions(K逆序对)
    1890. Money out of Thin Air(线段树 dfs转换区间)
    1350. Canteen(map)
    1521. War Games 2(线段树解约瑟夫)
    1003. Parity(并查集)
    1470. UFOs(三维树状数组)
    1471. Tree(LCA)
    1494. Monobilliards(栈)
  • 原文地址:https://www.cnblogs.com/sjjsxl/p/5021390.html
Copyright © 2011-2022 走看看