Boolan 第二周笔记

来源:互联网 发布:在u盘中安装ubuntu 编辑:程序博客网 时间:2024/05/08 00:54

#ifndef _RECTANGLE_#define _RECTANGLE_ class Shape{int no_;}; class Point{ int x_; int y_; public:Point(int x, int y) : x_(x),y_(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(); };inline Rectangle::Rectangle(int width, int height, int x, int y): width_(width), height_(height), leftUp_(new Point(x,y)){}inline Rectangle::Rectangle(const Rectangle& other): Shape(other), width_(other.width_), height_(other.height_){ if (other.leftUp_ != NULL) { this->leftUp_ = new Point(*(other.leftUp_)); } else { this->leftUp_ = NULL; }}inline Rectangle& Rectangle::operator = (const Rectangle& other){ if (this == &other) return *this; Shape::operator=(other); width_ = other.width_; height_ = other.height_; if (leftUp_ != NULL) { if (other.leftUp_ != NULL) { *leftUp_ = *(other.leftUp_); } else { delete leftUp_; leftUp_ = NULL; } } else { if (other.leftUp_ != NULL) { leftUp_ = new Point(*(other.leftUp_)); } } return *this;}Rectangle::~Rectangle(){ delete this->leftUp_;}#endif


Classes的两个经典分类:

  • Class without pointer member(s)
    complex
  • Class with pointer member(s)
    string

String class


String class

String s3(s1); // s3初值为s1,拷贝
s3=s2; //拷贝,引发与刚才不一样的函数

编译器给的默认的可以用,就用
但是这里不可以用,用的话会传指针,不是真的复制。

Big Three,三个特殊函数


Big Three,三个特殊函数

动态分配,而不是在类里面放一个数组。
所以是一个指针。

不能用编译器的,所以要写出来。
234是比 Complex 新增加的,Complex 里不曾出现
2.String 接受的是自己这种东西,所以叫拷贝构造
3.复制的是自己这种东西,拷贝赋值
4.
所有的类的定义,对 big3都不会加 const,因为必然要修改

ctor 和 dtor(构造函数和析构函数)


ctor 和 dtor(构造函数和析构函数)

2-1
要想到最后有一个结束符'\0'
最后一步,清理的函数。
动态内存,所以要清理。否则会造成溢出。
class 里有指针,多半要使用动态分配,有动态分配,就要在退出时释放这部分内存。

class with pointer members 必须有 copy ctor 和 copy op=(赋值assignment operator)


class with pointer members 必须有 copy ctor 和 copy op=(赋值assignment operator)

如果使用编译器默认,则在赋值时会拷贝指针,而不是数据。
看起来像是内容相同,但是 a 和 b 指向了相同的数据,改变 a 同时也会改变 b。

copy ctor(拷贝构造函数)


copy ctor(拷贝构造函数)

2-2
alias 叠名
是一件危险的事

copy assignment operator(拷贝赋值函数)


copy assignment operator(拷贝赋值函数)

2-3
赋值过程:
先把左边清空,然后建立一个和右边一样的空间,再把右边拷贝到左边。
首先,检测是不是自我赋值,不只是同名赋值,很可能是指针指向同一个类。如果相同,就直接返回指针。
然后再拷贝:

  1. 删掉
  2. 建立空间
  3. 拷贝内容

    赋值前

删掉

建立空间

拷贝内容

如果不检测自我赋值,会发生什么:

  1. 删掉了唯一值
  2. 无法建立空间,因为检测不出长度,出错

如果不检测自我赋值

output 函数


output 函数

要写操作符重载
有什么可以直接丢给 cout呢?有,写在 inline 里面的 get_c_str()

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


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


放在栈里的内容,在离开作用域后会自动删除
放在堆里的内容,需要自己手动删除

stack objects 的生命期


stack objects 的生命期


auto object

static local objects 的生命周期


static local objects 的生命周期


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

globe object 的生命周期


globe object 的生命周期

heap objects 的生命周期


heap objects 的生命周期

new:先分配 memory,再调用 ctor


new:先分配 memory,再调用 ctor


绝大多数的 new 被分解为三个部分:

  1. 调用 operator new,其内部调用 malloc(n),分配内存的函数
  2. 转换类型
  3. 调用构造函数,全名是 Complex::Complex(this,i,j)

new:先分配 memory,再调用 ctor

delete:先调用 dtor,再释放 memory


delete:先调用 dtor,再释放 memory
  1. 执行析构函数~String(ps),删除字符串占用的空间
  2. 释放内存 operator delete(ps),调用free(ps)

delete:先调用 dtor,再释放 memory

动态分配所得的内存块(memory block),in VC


动态分配所得的内存块(memory block),in VC

VC调试中Complex占用的,复数占用8B,调试占用32+4,cookie,42,共52B,总共占用64B(必须是16的倍数)所以有34B 的填充物
Release Mode,8B,cookie 占用42,共16B
cookie 内容00000041,4代表4
16,1代表已分配
VC调试中String 占用的,指针占用4B,调试占用32+4,cookie,42,共48B,没有填充物
Release Mode,4B,cookie 占用4
2,共12B,总共占用16B,其中4B为填充物。

动态分配所得的 array


动态分配所得的 array

2-1
Complex* p=new Complex[3];

array new 一定要搭配 array delete


array new 一定要搭配 array delete

不正确的用法少了[],少了[]并不会发生array占用的内存泄漏。
有[]调用3次析构函数
没有[]调用1次析构函数,有两个并不回收

编程实例

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;};inlineString::String(const char* cstr=0){    if (cstr){        m_data = new char[strlen(cstr)+1];        strcpy(m_data,cstr);    }    else{ //未指定初值        m_data = new char[1];        *m_data= '\0';    }}inlineString::~String(){    delete[] m_data;}inlineString::String(const String& str){    m_data = new char[ strlen(str.m_data) + 1];    strcpy(m_data,str.m_data);}inlineString& String::operator=(const String& str)//引用{    if (this == &str)//取地址        return *this;    //必须先判断是否自我赋值    delete[] m_data;    m_data = new char[ strlen(str.m_data)+1];    strcpy(m_data,str.m_data);    return *this;}

进一步补充:static


进一步补充:static

静态成员函数没有 this pointer,所以不能使用 this pointer 的功能。


进一步补充:static

静态的变量要在外面赋初值

进一步补充:把 ctors 放在 private 区


进一步补充:把 ctors 放在 private 区

只用一次的函数。构造函数放在 private 中,


进一步补充:把 ctors 放在 private 区

只有第一次调用的时候才会定义,这以后就会存在,并且只会有一份。

进一步补充:cout


进一步补充:cout

进一步补充:class template,类模板


进一步补充:class template,类模板

进一步补充:function template,函数模板


进一步补充:function template,函数模板

把责任分开,很有必要
这种东西叫做算法

进一步补充:namespace


进一步补充:namespace
  • using directive
    using namespace std;
  • using declaration
    using std:cont;
  • 用全名

更多细节与深入



作者:一般的路人丙
链接:http://www.jianshu.com/p/7aad5440aa68
來源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

原创粉丝点击