勿在浮沙筑高台--P7-P9

总:Classes的两个经典分类

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

一. string class

#ifndef  __MYSTRING__             string.h
#define __MYSTRING__

class String
{
...
};

String::function(...) ...
Global::function(...) ...

#endif
int main(){
  String s1();
  String s2("hello");

  String s3(s1);
  cout << s3 << endl;
  s3 = s2;
  cout << s3 <<endl;
}

二. Big Three, 三个特殊函数

  • 一般创建一个字符指针,指向字符串。因为字符串的大小不确定。
  • Big Three:拷贝构造、拷贝赋值、析构函数。
  • 拷贝构造:输入参数为string类型。
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;
}

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

  • new动态分配内存,所以需要在析构函数中 delete。
inline 
String::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';
    }
}

inline 
String::~String()
{
    delete[] m_data;
}
{
   String s1();
   String s2("hello");

   String* p = new String("hello");
   delete p;
}

四. 必须有拷贝构造和拷贝赋值函数

  • 浅拷贝:别名
  • 深拷贝

五. 拷贝构造函数

inline 
String:String(const String& str){
    m_data = new char[ strlen(str.m_data) +1 ]
    strcpy(m_data, str.m_data)
}

{
    String s1("hello");
    String s2(s1);
 // String s2 = s1;
}

六. 拷贝赋值函数

  • 把一个对象s1拷贝给另外一个对象s2。
  • (1)先把s2清空,(2)再构造一块和s1相同大小的空间,(3)再拷贝回去。
inline
String& String::opeator=(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;
}

七. output函数

#include<iostream.h>
ostream operator<<(ostream& os, const String& str){
    os<< str.get_c_str();
    return os;
}

{
    String s1("hello");
    cout << s1;
}

八. stack 栈,heap堆

  • Stack,存在于某作用域(scope)的一块内存空间。例如当你调用函数,函数本身会形成一个stack用来放置所接收的参数,以及返回地址。
  • 在函数本体内声明的任何变量,其所使用的的内存块都取自stack。
  • Heap, 或 system heap,指有操作系统提供的一块global内存空间,程序可以动态分配若干区块。
class Complex{...};
...
{
    Complex c1(1, 2);
    Complex* p = new Complex(3);
}

九. objects的生命期

class Complex{...};
...
{
   Complex c1(1, 2);
}
  • c1是stack object,其生命在作用域scope结束结束。这种作用域内的object,成为 auto object,因为会被自动清理。
class Complex{...};
...
{
   static Complex c2(1, 2);
}
  • c2是static object, 其声明在作用域(scope)结束之后仍然存在,直到整个程序结束。
class Complex {...};
...
Complex c3(1, 2);

int main(){
 ...
}
  • c3是global object, 其声明在整个程序结束后才结束,也可以视为一种static object, 其作用域是整个程序。
class Complex {...};
...
{
    Complex* p = new Complex;
    ....
    delete p;
}
  • p是heap object,其声明在deleted之后结束。
class Complex {...};
...
{
    Complex* p = new Complex;
}
  • 会出现内存泄露, p所指的heap object 仍然存在,但指针p的声明已经结束了,作用域之外也看不到p,没办法释放内存。

十. new: 先分配memory,再调用构造函数

Complex *pc;

void* mem = operator new( sizeof(Complex) ); //分配内存
pc = static_cast<Complex*>(mem);                   //转型
pc->Complex::Complex(1, 2);                             //构造函数
// Complex::Complex(pc, 1, 2); 

十一. 先调用析构函数,再释放memory

delete ps;

String::~String(ps);      //析构函数
operator delete(ps);     //释放内存, 内部调用free(ps)
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容