美文网首页
Boolan:第二周

Boolan:第二周

作者: 常春藤上的蜗牛 | 来源:发表于2017-10-25 08:12 被阅读0次

    三大函数:拷贝构造、拷贝赋值、析构

    class String
    {
    public:
      String(const char* cstr = 0);
      String(const String& str);
      String& operator=(const String& str);
     ~ String();
      char* get_c_str() const {return m_data;}
    private:
      char* m_data;
    };
    

    如果所写的类中带有指针,不能使用编译器中自动生成的拷贝构造和拷贝赋值函数,必须自己重写一个。

    堆、栈与内存管理

    重载的operator<<函数必须是一个函数,不能写成一个成员函数,因为如果写成成员函数,<<在使用的时候必须在cout的左侧(<<cout)不符合用户的使用习惯,因此需要将其写成一个全局函数。

    所谓stack(栈),所谓heap(堆)

    stack:
    存在于某个作作用域的一块内存空间。在函数体内声明的任何变量,其所使用的内存块都取自stack
    Heap:
    指由操作系统提供的一块global内存空间,程序可动态分配从某种获得若干区块。


    local Object生命周期

    class Complex{...};
    ...
    {
      Complex c1 (1, 2);
    }
    

    c1被自动释放
    static local object生命周期

    class Complex{...};
    ...
    {
      static Complex c1 (1, 2);
    }
    

    c2生命在作用域(scope)结束之后仍然存在,直到整个程序结束。

    不带指针类的new和delete

    new:

    image.png

    其中的opreator new()是C++中定义的一个特殊函数,在其内部中是调用malloc(n)函数进行内存的分配的。
    delete:

    image.png
    同样的operator delete()是C++中的一个特殊函数,内部调用的free
    带有指针类的new和delete

    new:

    image.png
    delete:
    image.png
    调用析构函数的时候,会释放类中指针所占的内存。
    动态分配所得到的内存块(memory block), in VC
    image.png

    上面图片中,内存分配较多的是在debug模式下分配的内存。
    橘色的部分是Cookie中存放的是内存释放时需要的信息,绿色的部分是复数对象所占用的内存,算出的内存是52,由于内存的总数是16的倍数,因而需要填充12bit的内存,一共为64。64写成16进制为00000040,由于是系统分配给对象的内存,因此橘色部分是末尾数字为1,00000041

    动态分配所得的array
    动态分配所得的array

    array new 一定搭配array delete

    array delete
    如果一个类中含有指针成员,进行array new之后,必须搭配使用array delete否则会产生内存泄漏,其中泄漏的部分是,类中指针成员并没有得到释放,如果该类中不包含指针成员,是不会造成内存泄漏的。
    第二周作业
    #pragma once
    #include <iostream>
    
    class Shape
    {
        int no;
    };
    class Point
    {
    public:
        Point(int x, int y) : x(x), y(y) {}
        Point& operator=(const Point& point)
        {
            if (this == &point)
                return *this;
            this->x = point.x;
            this->y = point.y;
        }
        ~Point(){}
        int getX() const { return this->x; }
        int getY() const { return this->y; }
    private:
        int x;
        int y;
    };
    class Rectangle : public Shape
    {
        int width;
        int height;
        Point * leftUp;
    public:
        Rectangle(int width, int height, int x, int y);
        Rectangle(const Rectangle& other);
        Rectangle& operator=(const Rectangle& other);
        ~Rectangle();
    
        int GetWidth() const;
        int GetHeight() const;
        Point* GetPoint() const;
    };
    
    Rectangle::Rectangle(int width, int height, int x, int y)
    {
        this->width = width;
        this->height = height;
        leftUp = new Point(x, y);
    }
    
    Rectangle::Rectangle(const Rectangle & other)
    {
        this->width = other.width;
        this->height = other.height;
        this->leftUp = new Point(other.leftUp->getX(), other.leftUp->getY());
        //this->leftUp = other.leftUp;
    }
    Rectangle& Rectangle::operator=(const Rectangle& other)
    {
            //判断地址是否相同
        if (this == &other)
            return *this;
        this->width = other.width;
        this->height = other.height;
        this->leftUp = new Point(other.leftUp->getX(), other.leftUp->getY());
        // 这种写法是错误的,这种写法会使得this->leftUp和other.leftUp指向同一个对象,
        //当析构的时候就会出现问题,当其中的一个指针指向的内被释放时,那么另外一个指针就会成为野指针,再delete会崩溃
        //this->leftUp = other.leftUp;  
        return *this;
    }
    
    Rectangle::~Rectangle()
    {
        delete leftUp;
    }
    
    int Rectangle::GetWidth() const
    {
        return this->width;
    }
    int Rectangle::GetHeight() const
    {
        return this->height;
    }
    Point* Rectangle::GetPoint() const
    {
        return this->leftUp;
    }
    std::ostream& operator<<(std::ostream& os, const Rectangle& rec)
    {
        os << rec.GetWidth() << rec.GetHeight() 
            << rec.GetPoint()->getX()
            << rec.GetPoint()->getY();
        return os;
    }
    
    

    static

    static
    上图中解释了this指针,cout << c1.real(); this指针相当于&c1。调用非静态成员函数,this指向的即为该调用者。
    static
    其中double Account::m_rate = 8.0;为静态成员变量的定义。
    image.png
    该模式为单例模式,由于构造函数是私有的,因而外界是不能创建对象的,成员A是静态的。
    image.png
    这种写法相对上面的好处是,上面一种静态变量一开始就占有着内存,而第二种只有创建对象的时候才会开始占有内存。

    相关文章

      网友评论

          本文标题:Boolan:第二周

          本文链接:https://www.haomeiwen.com/subject/vioxpxtx.html