C++典型String类的编写(包含move实现)

C++面向对象是区别于C的典型特征,C++中类有两种不同的类型。

  1. 数据成员不含指针的;典型代表有Complex类。
  2. 数据成员含指针的;典型为字符串String类。

C++11中提出了新概念move semantics(可译为移动语义),可以简单理解为移动语义为**“浅拷贝”**,具体可查资料了解。

下面贴出String类的具体代码:

#ifndef __STRING_H_
#define __STRING_H_ 

#include <cstring>
#include <iostream>

//典型String类的编写
class String {
public:
    String(const char* cstr = 0, int clen = 0);
    String(const String& str);
    String(String&& str);
    String& operator=(const String& str);
    String& operator=(String&& str);
    ~String();

    int size() const{
        return len;
    }

    char* get_c_str() const {
        return pstr;
    }
private:
    char* pstr;
    int len;
};

inline
String::String(const char* cstr, int clen) { // 声明的时候有默认值,定义的时候不需要默认值,会出现重定义错误
    std::cout << "调用了ctor" << "\n"; 
    if (cstr) {
        pstr = new char[strlen(cstr) + 1];
        len = strlen(cstr);
        strcpy(pstr, cstr); 
    }
    else {
        pstr = new char[1];
        len = 0;
        *pstr = '\0';
    }
}

inline 
String::String(const String& str) {
    std::cout << "调用了copy ctor" << "\n";
    pstr = new char[str.len + 1];
    len = str.len;
    strcpy(pstr, str.pstr);
}

inline 
String& String::operator=(const String& str) {
    std::cout << "调用了copy assignment" << "\n";
    if (this == &str) {
        return *this;
    }
    delete[] pstr;
    pstr = new char[str.len + 1];   /* 类的拷贝复制和拷贝构造乃至成员函数都能访问同类形参中的私有变量 */
    len = str.len;
    strcpy(pstr, str.pstr);
    return *this;
}

inline
String::String(String&& str) {
    std::cout << "调用了move ctor" << std::endl;
    if (str.pstr != NULL) {
        pstr = str.pstr;
        str.pstr = nullptr;
        len = str.len;
    }
}

inline
String& String::operator=(String&& str) {
    std::cout << "调用了move assignment" << std::endl;
    if (this != &str) {
        delete[] pstr;
        pstr = str.pstr;
        str.pstr = nullptr;
        len = str.len;
    }
    return *this;
}

inline
String::~String() {
    std::cout << "调用了dtor" << "\n";
    delete[] pstr;
}

/* 将operator<<重载为全局函数好一点(相比于重载为成员函数)
   1. 重载为成员函数
   ostream& operator<<(ostream& os) {
       os << pstr;
       return os;
   }
   调用的时候只能这样调用:s << cout(即 s.operator<<(cout)), 和我们的常用手法相悖
   
   2. 重载为全局函数
*/
std::ostream& operator<<(std::ostream& os, const String& s) {
    os << s.get_c_str();
    return os;
}

// 还可以重载operator<,用来比较两个String的大小
bool operator<(const String& s1, const String& s2) {
    return strcmp(s1.get_c_str(), s2.get_c_str()) < 0;
}


#endif //__STRING_H_

下面贴出测试代码:

#include <iostream>
#include "string.h"
using namespace std;

int main(int argc, char** argv) {
    String s1("Ray");
    String s2("Shan");
    String s3(s2);
    String s4 = s3;

    //test move ctor
    String s5(std::move(s1));
    //test move assignment
    s4 = move(s2);

    s3 = s4;

    if (s5 < s4) {
        cout << s5 << " < " << s4 << endl;
    }
    else {
        cout << s5 << " >= " << s4 << endl; 
    }

    cout << s5 << "\n" << s4 << "\n";

    cout << s3 << "的长度为" << s3.size() << "\n";

    return 0;
}

结果:
pic1
右值引用的拷贝构造和拷贝赋值函数中的参数都不能加const。

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值