C++学习笔记(3)——拷贝构造与MyString类实现

引用:

(和引用变量名要区分开,这里是一种类型)

本质:​ 给内存段取别名

int main(){
    
    
    int n = 10;
    int& m = n;	//引用类型
    m = 666;
    printf("n:%d",n);
    while(1);
	return 0;
}
    

​ &:单目 只有左操作数 取地址

​ &:双目 左值:类型名 右值:标示符 修饰:引用

​ 定义引用类型的变量:

​ 类型名& 引用变量名 = 变量名;

​ 引用类型的变量的使用和普通变量没有区别

特性:

​ 1.引用必须声明

引用和指针的区别:

​ 1.引用不占内存,指针需要强制制定,占内存(root作用)

​ 2.引用必须初始化,而指针不必

​ 3.引用不能指向其他内存段,而指针可以

​ 4.const 修饰引用,引用绑定内存段不能写访问;const 修饰指针还是类型

​ 5.sizeof的结果不同

​ 6.引用不可为空,指针可 = None

​ 7.指针是变量,引用时内存段的别名

/*
void swap(int a,int b){//直接赋值
	int t;
    t = a;
    a = b;
    b = t;
}*/
void swap(int* a,int* b){
    
    //指针地址
    int t = *a;
    *a = *b;
    *b = t;
}
void swap(int& a,int& b){
    
    //引用构造
	int t = a;
    a = b;
    b = t;
}
int main(){
    
    
    int n =10,m =100;
    printf("Before swap n:%d,m:%d\n",n,m);
    swap(&n,&m);
    swap(&n,&m);
    printf("After swap n:%d,m:%d\n",n,m);
    
    while(1);
    return 0;
}

拷贝构造:用对象构造对象

​ 缺省构造函数和缺省拷贝构造函数

#include "stdafx.h"
class A {
    
    
	int n = 0;
public:
	A() {
    
    printf("无参构造\n");}
	A(int n) : n(n) {
    
     printf("有参构造\n"); }
	//A(A* a) {};//对象的地址构造对象
	A(const A& a) {
    
     //防止引用过程中修改a的值
	this->n = a.n;
	//a.n = 666;
	printf("复制拷贝构造函数\n"); 
	}
	void show() {
    
     printf("n:%d\n", this->n); };
};

int main()
{
    
    
	A a;
	a.show();
	A b(1);
	b.show();
	A c(a);
	c.show();
	A d = b;
	d.show();
	b.show();
	while (1);
    return 0;
}

深拷贝:重新分配内存,拷贝数据

浅拷贝:直接赋值,保存指针变量地址

如果对象成员变量是基本数据类型,浅拷贝没问题;但如果成员变量是指针变量,要使用深拷贝

缺省的拷贝构造函数都是浅拷贝

定义类的时候,要自定义构造器和拷贝构造器。如果定义类的变量是指针变量,要使用深拷贝。

#include<cstring>
class MyString {
    
    
	char* pStr;
public:
	MyString() {
    
     pStr = NULL; }
	MyString(char* str) {
    
    
		pStr = new char[strlen(str)];
		memcpy(pStr, str, strlen(str));
		printf("有参构造\n");
	}
	MyString(const MyString& str) {
    
    
		pStr = str.pStr;
		printf("拷贝构造\n");
	}
	~MyString() {
    
    
		delete[] pStr;//删除指向的全部字符串
		printf("析构函数\n");
	}
};
int main() {
    
    
	//MyString str1("haha");
	//MyString str2(str1);

	MyString* ps1 = new MyString("强哥好帅");
	MyString* ps2 = new MyString(*ps1);//拷贝构造
	delete ps1;
	delete ps2;	//出现错误,原因:ps1与ps2指向同一内存段,不能重复释放

	while (1);
	return 0;
}

//变法
#include<cstring>
class MyString {
    
    
	char* pStr;
public:
	MyString() {
    
     pStr = NULL; }
	MyString(char* str) {
    
    
		pStr = new char[strlen(str)];
		memcpy(pStr, str, strlen(str));
		printf("有参构造\n");
	}
	MyString(const MyString& str) {
    
    
		/*
        pStr = str.pStr;//直接赋值,浅拷贝
		*/
        pStr = new char[strlen(str.pstr)+1];
        memcpy(pStr,str.pStr,strlen(str.pStr));
		printf("拷贝构造\n");
	}
	void change() {
    
    
		strcpy(pStr, "强哥超级帅");
	}
	void show() {
    
    
		printf("Str:%s\n", pStr);
	}
	~MyString() {
    
    
		delete[] pStr;//删除指向的全部字符串
		printf("析构函数\n");
	}
};
int main() {
    
    
	//MyString str1("haha");
	//MyString str2(str1);

	MyString* ps1 = new MyString("强哥好帅");
	ps1->show();
	

	MyString* ps2 = new MyString(*ps1);//拷贝构造
	ps2->show();
	ps1->change();
	ps1->show();
	ps2->show();
	delete ps1;
	delete ps2;	//出现错误,原因:ps1与ps2指向同一内存段,不能重复释放

	while (1);
	return 0;
}

#endif

实现MyString类

题目:添加成员函数,功能时返回当前字符串中参数字串个数

size_t getChildStrNum(char* str);

举例:当前字符串为abcdefgabc,参数ab,返回2

// MyString.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
class MyString {
    
    
	char* pStr = NULL;
	size_t size = 0;
public:
	MyString();
	MyString(char* str);
	MyString(const MyString& str);
	~MyString();
	//获取大小
	size_t getSize(char* str);
	//比较
	int compare(char* str);
	int compare(const MyString& str);
	//拼接
	void strcat(char* str);
	void strcat(const MyString& str);
	//转换大小写
	void change();
	//显示
	char* c_str();
	//返回子串数目
	size_t getChildStrNum(char* str);
private:
	//获取长度
	size_t _getlen(char* str);
};
MyString::MyString() {
    
    
	pStr = new char[1];
	pStr = 0;
}
MyString::MyString(char* str) {
    
    
	size_t len = _getlen(str) + 1;
	pStr = new char[len];
	memcpy(pStr,str,len);
	size = len - 1;
}
MyString::MyString(const MyString& str) {
    
    
	size = str.size;
	pStr = new char[size +1];
	memcpy(pStr, str.pStr, size+1);
}
MyString::~MyString() {
    
    
	if (pStr)
		delete[] pStr;
	pStr = NULL;
	size = 0;
}
int MyString::compare(char* str) {
    
    
	char* p1 = this->pStr;
	char* p2 = str;

	while (*p1 != '\0' && *p2 != '\0') {
    
    
		if (*p1 > *p2) return 1;
		if (*p1 < *p2) return -1;
		p1++;
		p2++;
	}
	if (*p1 > *p2) return 1; //和0去比较
	if (*p1 < *p2) return -1;
	return 0;//相等
}
int MyString::compare(const MyString& str) {
    
    
	char* p1 = this->pStr;
	char* p2 = str.pStr;

	while (*p1 != '\0' && *p2 != '\0') {
    
    
		if (*p1 > *p2) return 1;
		if (*p1 < *p2) return -1;
		p1++;
		p2++;
	}
	if (*p1 > *p2) return 1; //和0去比较
	if (*p1 < *p2) return -1;
	return 0;//相等
}
size_t MyString::getSize(char* str) {
    
    
	return size;
}
void MyString::strcat(char* str) {
    
    
	//1.计算长度和
	size_t sumlen = size + _getlen(str);
	//2.新开内存
	char* cStr = new char[sumlen+1];
	//3.拷贝数据
	memcpy(cStr, pStr, size);
	memcpy(cStr+size , str, (_getlen(str)+1));//结束符号
	//4.释放原有内存段
	delete[] pStr;
	//5.pStr指向新开内存段,size赋值
	pStr = cStr;
	size = sumlen;
}
void MyString::strcat(const MyString& str) {
    
    
	//1.计算长度和
	size_t sumlen = size + str.size;
	//2.新开内存
	char* cStr = new char[sumlen + 1];
	//3.拷贝数据
	memcpy(cStr, pStr, size);
	memcpy(cStr + size, str.pStr, str.size+1);//结束符号									 //4.释放原有内存段
	delete[] pStr;
	//5.pStr指向新开内存段,size赋值
	pStr = cStr;
	size = sumlen;
}
void MyString::change() {
    
    
	char *p = pStr;
	while (*p) {
    
    
		//"abc" "ABC"
		if (*p >= 'A' && *p <= 'Z') *p += 32;//大写变小写
		else if (*p >= 'a' && *p <= 'z') *p -= 32;//小写变大写
		p++;
	}
}
//void MyString::change() {}
char* MyString::c_str() {
    
    
	return pStr;
}

size_t MyString::_getlen(char* str) {
    
    
	size_t len= 0;
	char* p = str;
	while (*p) {
    
    
		len += 1;
		p++;
	}
	return len;
}
size_t MyString::getChildStrNum(char* str) {
    
    
	char* p = pStr;
	size_t num = 0, len = 0;
	len = _getlen(str);
	while (*p) {
    
    
		if (*p == *str) {
    
    
			for (size_t i = 0; i < len;i++) {
    
    
				if (*(p+i) != *(str + i))break;
				if (i == len - 1)num += 1;
			}
		}
		p++;
	}
	return num;
}
int main()
{
    
    
	//测试比较
	MyString str1("abCdefgabc");
	MyString str2("kakak");
	printf("%d\n", str1.compare("abcdefg"));
	printf("%d\n", str1.compare(str2));
	str1.strcat(str2);
	//str1.strcat("你好");
	printf("%s\n", str1.c_str());
	str1.change();
	printf("%s\n", str1.c_str());
	str1.change();
	printf("%s\n", str1.c_str());
	printf("%d\n", str1.getChildStrNum("a"));
	while (1);
    return 0;
}

运行结果:
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/weixin_43357695/article/details/105307775