构造和析构的几点注意事项

  1. 变量要初始化,初始化尽量使用初始化列表。如果不初始化,变量的值是随机不确定的。
class Point {
    
    
    int x;
    int y;
};
// 改进之后后
class Point {
    
    
   public:
    Point(int x, int y) : _x(x), _y(y) {
    
    }

   private:
    int _x;
    int _y;
};
  1. 私有析构函数,类对象不能在栈上分配空间. 只能在堆上分配,但不能delete直接释放。
#include <iostream>
using namespace std;

class Point {
    
    
   public:
    Point(int x, int y) : _x(x), _y(y) {
    
    }
    void destory() {
    
     delete this; }
   private:
    ~Point() {
    
    }

   private:
    int _x;
    int _y;
};

int main(int argc, char const *argv[]) {
    
    
    //Point p(1, 2);// error
    Point *p1 = new Point(1, 2);
    //delete p1;//error
    p1.destory();
    return 0;
}
  1. 屏蔽new和delete, 对象只能在栈上分配
#include <iostream>
using namespace std;

class Point {
    
    
   public:
    ~Point() {
    
    }
    Point(int x, int y) : _x(x), _y(y) {
    
    }
    // 删除或者私有new 和 delete
    void* operator new(size_t size) = delete;
    void operator delete(void* ptr) = delete;
    //    private:
    //     void* operator new(size_t size);
    //     void operator delete(void* ptr);

   private:
    int _x;
    int _y;
};

int main(int argc, char const* argv[]) {
    
    
    Point* p1 = new Point(1, 2);//error
    delete p1;
    return 0;
}
  1. 多态基类声明为虚析构函数,否则可能会导致内存泄漏。代码如下
    反之,不要设置虚析构函数,导致冗余内存。
#include <iostream>
using namespace std;

class Base {
    
    
   public:
    Base() {
    
     a = new char[100]; }
    ~Base() {
    
    
        cout << __func__ << endl;
        delete[] a;
    }

   private:
    char* a;
};
class Derived : public Base {
    
    
   public:
    Derived() {
    
     b = new char[100]; }
    ~Derived() {
    
    
        cout << __func__ << endl;
        delete[] b;
    }

   private:
    char* b;
};

int main(int argc, char const* argv[]) {
    
    
    Base* d = new Derived();
    delete d;
    return 0;
}

Output:

[root@localhost poco_demo]# g++ tt.cpp -std=c++11 -o tt
[root@localhost poco_demo]# ./tt
~Base
  1. 不要在析构函数中抛出异常,这样可能会导致内存无法释放等错误。正确的做法是,捕获并处理掉这些错误,让析构正常结束,而不是一层层抛出。

  2. 不要再析构和构造函数,使用虚函数。虚函数是通过虚函数表控制,类通过虚函数表指针,访问虚函数表。虚函数表指针作为一个成员变量,在构造时初始化,析构时结束生命周期。在继承体系中,这样做会更混乱。

  3. 不要私有一个虚函数,因为这没什么意义。只要拿到_vptr,就可以访问虚函数表,进而绕过private访问虚函数。

猜你喜欢

转载自blog.csdn.net/niu91/article/details/109938875