C++ study notes (3) - copy construction and MyString class implementation

Quote:

(To be distinguished from reference variable names, here is a type)

Essence: Alias ​​the memory segment

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

​ &: Monocular only takes the address of the left operand

​ &: binocular lvalue: type name rvalue: identifier modification: reference

​ Define a variable of reference type:

​ type name & reference variable name = variable name;

​ There is no difference between the use of reference type variables and ordinary variables

​Features :

1. References must be declared

The difference between references and pointers:

1. References do not occupy memory, pointers need to be made mandatory, occupying memory (root role)

2. References must be initialized, but pointers do not

3. References cannot point to other memory segments, while pointers can

​ 4. const modified references, references to bound memory segments cannot be written and accessed; const modified pointers are still types

5. The result of sizeof is different

6. The reference cannot be empty, the pointer can be = None

7. The pointer is a variable, the alias of the memory segment when referencing

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

Copy construction: constructing an object from an object

​ Default constructor and default copy constructor

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

Deep copy: reallocate memory, copy data

Shallow copy: direct assignment, save pointer variable address

If the object member variable is a basic data type, shallow copy is fine; but if the member variable is a pointer variable, use deep copy !

The default copy constructors are all shallow copies

When defining a class, you need to customize the constructor and copy constructor. If the variable defining the class is a pointer variable, use deep copy.

#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

Implement the MyString class

Topic: Add a member function that returns the number of parameter strings in the current string

size_t getChildStrNum(char* str);

Example: the current string is abcdefgabc, the parameter ab returns 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;
}

operation result:
insert image description here

Guess you like

Origin blog.csdn.net/weixin_43357695/article/details/105307775