C++ study notes (3) - copy construction and MyString class to achieve some functions
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: