通过 String 类学习的知识

2021-11-05  本文已影响0人  madao756

源码

// string.h
#ifndef __MYSTRING__
#define __MYSTRING__

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;
};

#include <cstring>

inline
String::String(const char* cstr)
{
   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;
}

inline
String& 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;
}

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

#include <iostream>
using namespace std;

ostream& operator<<(ostream& os, const String& str)
{
   os << str.get_c_str();
   return os;
}

#endif
// string_test.cpp

   
#include "string.h"
#include <iostream>

using namespace std;

int main()
{
  String s1("hello"); 
  String s2("world");
    
  String s3(s2);
  cout << s3 << endl;
  
  s3 = s1;
  cout << s3 << endl;     
  cout << s2 << endl;  
  cout << s1 << endl;      
}

学习到的知识

原因是如果使用默认的,那么只是浅拷贝。析构函数是用来析构分配的内存的。如果不释放分配的内存那么会导致内存泄漏的问题。

inline
String& 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;
}


比如如果是自赋值的话,上面的代码会把自己的 m_data 释放掉,造成错误的结果。

释放的时候,如果创建的时候以一种数组的形式创建的那么一定要 delete[]。

先使用 malloc 分配内存,再调用构造函数

先调用析构函数,再释放分配的内存

#include <iostream>

using namespace std;

class Account {
public:
    static double m_rate;
};


int main() {

    Account a;

    cout << a.m_rate << '\n';

    return 0;
}

这样写会报错。

  1. 通过 object 调用
  2. 通过 class name 调用
#include <iostream>

using namespace std;

class A {
public:
    static void foo(){
        cout << "foo" << '\n';
    }
};


int main() {
    A::foo();

    A a;
    a.foo();

    return 0;
}

就是在类的前面定义一个模板:

template<typename T>
class XXX{};

然后在类中就可以使用这个预定义的 T。比如:

template<typename T>
class Rectangle{
public:
    Rectangle(const T w = 0, const T h = 0):w(w),h(h){}
    T size() {
        return w * h;
    }
private:
    T w, h;
};

然后在使用的时候指定这个模板是什么。比如:

int main() {

    Rectangle<double> r(1.1, 2.2);
    cout << r.size() << '\n';

    return 0;
}

比如最小值(比 go 真的简单太多了)

#include <iostream>
#include <utility>

using namespace std;

template<class T>
inline
const T& myMin(const T& x, const T& y) {
    return x < y ? x : y;
}


class Stone{
public:
    Stone(const double size, string name):size(size),name(std::move(name)){}
    inline bool operator<(const Stone& s) const {
        return this->size < s.size;
    }
    inline string get_name() const{
        return this->name;
    }

private:
    string name;
    double size;
};

inline ostream& operator<<(ostream& os, const Stone& s) {
    os << s.get_name();
    return os;
}


int main() {
    cout << myMin(1.1, 2.2) << '\n';
    cout << myMin(Stone(10, "min_stone"), Stone(20, "big_stone")) << '\n';

    return 0;
}

上一篇 下一篇

猜你喜欢

热点阅读