Boolan:第二周

2017-10-25  本文已影响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
这种写法相对上面的好处是,上面一种静态变量一开始就占有着内存,而第二种只有创建对象的时候才会开始占有内存。
上一篇下一篇

猜你喜欢

热点阅读