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;
}
运行结果: