C++学习笔记(2)

目录

一.C++与C语言结构体的区别

1.struct关键字

2.C++结构体中允许函数存在

二.C语言和C++的动态内存申请

1.C语言的malloc,calloc,realloc。

2.C++的动态内存申请

(1)单个变量的内存申请

(2)数组的动态内存申请

(3)结构体动态内存申请

三.内存池

四.string类型

1.创建string

2.string基本操作

(1)赋值拷贝

(2)连接

(3)比较

3.C语言的字符串跟C++的string有何区别

4.其他有意思的操作


一.C++与C语言结构体的区别

1.struct关键字

定义时不需要 “struct” 关键字,直接用结构体名即可。

struct A
{
	char name[20];
	int age;
	//.....
};
int main()
{
	struct A a; //C语言需要加struct
	A aa; //C++可以省略
}

2.C++结构体中允许函数存在

在C++中,我们可以把整个结构体看作是一个对象,这个对象里面的数据成员叫做这个对象的属性,而在这个对象里声明的成员函数叫做这个对象的行为或者方法

成员函数的实现可以是在结构体内,也可以在结构体外。在结构体外实现成员函数,需要用结构体名对函数加以限定

struct A
{
	char name[20];
	int age;
	void Fun();
};
void A::Fun()
{
	//...
}

在C++的结构体中,其成员函数是可以直接访问结构体内其他成员的。

void A::Fun()
{
	cout << age << endl;
}

在调用方面,C++跟C语言基本一致,一般有这三种调用方式:

struct A
{
	char name[20];
	int age;
	void Fun();
};
void A::Fun()
{
	cout << age << endl;
}
int main()
{
	A a = {"小蓝",18};
	A* p = &a;
	a.age = 19;       //对象.成员
	p->age = 20;      //对象指针->成员
	(*p).age = 21;    //(*对象指针).成员
}

此外,根据上次学的引用类型的知识,通过把引用充当返回值,我们可以在结构体中创建一个能让外部改变结构体内部属性的接口,具体实现如下:

struct A
{
	char name[20];
	int age;
	int& getAge();
};
int& A::getAge()
{
	return age;
}
int main()
{
	A a = {"小蓝",18};
	a.getAge() = 19;
	//其实就等价于:a.age = 19;
	cout << a.age << endl;
	//打印结果为19
}

在结构体中这种方法看起来有点傻哈哈,但是在类中就有访问权限的问题,这种方法就方便起来了,有关类的介绍会在接下来的文章中更新的,这里先按下不表。

二.C语言和C++的动态内存申请

1.C语言的malloc,calloc,realloc。

简单来说,malloc是不带初始化的动态内存申请。

int main()
{
	int* pMNum = (int*)malloc(sizeof(int) * 3);
	for (int i = 0; i < 3; i++)
	{
		cout << pMNum[i] << " ";
	}
	cout << endl;
}

 可以看到,打印出来的是未被初始化的垃圾值,再来看看有进行初始化的calloc:

int main()
{
	int* pCNum = (int*)calloc(3,sizeof(int));
	for (int i = 0; i < 3; i++)
	{
		cout << pCNum[i] << " ";
	}
	cout << endl;
}

可以看到,申请的内存变量都被初始化为了0。

而 realloc 函数的作用是在原来申请过的动态内存的基础上进行扩充,注意,扩充之后的空间一定要比原来的大。

int main()
{
	int* p = (int*)calloc(1, sizeof(int));
	if (!p) return 0;
	(*p) = 1999;
	p = (int*)realloc(p, sizeof(int)*3);
	if (!p) return 0;
	p[1] = 1;
	p[2] = 2;
	for (int i = 0; i < 3; i++)
	{
		cout << p[i] << " ";
	}
	free(p);
	return 0;
}

 

可以看到,原有的数据仍然储存在堆区中,没有消失,只是对它进行了扩充。

2.C++的动态内存申请

(1)单个变量的内存申请

单个变量动态内存申请时用小括号。

int main()
{
	//申请时不做初始化
	int* pInt = new int;
	*pInt = 123;
	delete pInt;
	pInt = nullptr;
	//申请时初始化
	int* pNum = new int(123);
	delete pNum;
	pNum = nullptr;
}

(2)数组的动态内存申请

数组的动态内存申请用大括号。下面是一维数组的动态内存申请:

int main()
{
	//不初始化
	int* pInt = new int[3];
	delete[] pInt;
	pInt = nullptr;
	//初始化
	int* pNum = new int[3]{ 1,2,3 };
	delete[] pNum;
	pNum = nullptr;
}

要特别注意,不管是C语言还是C++,涉及到堆区字符串的初始化时,不能直接赋值,否则会出现意想不到的效果,下面用代码来展示一下:

int main()
{
	const char* pstr1 = new char[15];
	const char* pstr2 = pstr1;
	pstr1 = "I Love C++";
	cout << pstr1 << "\t" << pstr2 << endl;
}

可以看到,这里动态申请的空间里的东西并没有发生变化,这里所谓的赋值只是改变了pstr1指针的指向。想要赋值可以用strcpy函数。

二维数组的动态内存申请其实跟C语言的差不多,都是先申请完二级指针的空间,再分别给数组里面的指针申请动态内存,具体如下:

​
int**& NewArr2D(int row,int col)
{
	int** arr = new int* [row];
	for (int i = 0; i < row; i++)
	{
		arr[i] = new int[col];
	}
	return arr;
}
int main()
{
	int** arr = NewArr2D(2, 3);
	int cnt = 0;
    //初始化
	for (int i = 0; i < 2; i++)
	{
		for (int j = 0; j < 3; j++)
		{
			arr[i][j] = cnt++;
		}
	}
    //打印
	for (int i = 0; i < 2; i++)
	{
		for (int j = 0; j < 3; j++)
		{
			cout << arr[i][j] << " ";
		}
		cout << endl;
	}
	delete[] arr;
}


​

可以看到打印成功啦!

(3)结构体动态内存申请

大体跟数组的动态内存申请一样。

struct A
{
	char* name;
	int age;
	void print();
};
void A::print()
{
	cout << name << " " << age << endl;
}
int main()
{
	A* pA1 = new A;
	pA1->name = new char[18];
	strcpy_s(pA1->name, 18,"小蓝");
	pA1->age = 18;
	pA1->print();
	delete pA1->name;
	delete[] pA1;
}

我们可以看到,申请的结构体中如果有指针,需要二次申请,才能使用,且申请跟释放的顺序是相反的,即申请内存时是 “从大到小” ,而释放内存时是 “从小到大” ,如果顺序颠倒,会发生重复释放。

三.内存池

这里要介绍的是如何进行内存的综合管理。

我们知道,C语言中动态申请的内存统一存储在堆区,而C++中 “new” 出来的内存是在 “自由存储区” 中。如何理解 “自由” 二字?

new(申请内存开始的位置)

可以看到,所谓的自由,就是可以自由选择动态申请的内存从哪里开始储存,来分析以下代码:

void textMemory()
{
	char* memorySum = new char[1024];
	int* pSum = new(memorySum) int[3]{ 1,2,3 };
	char* pChar = new(memorySum + sizeof(int) * 3) char[20]{ "I Love C++" };
	delete[] memorySum;
}

首先我们申请了一块很大的缓冲区 “memorySum” ,然后在这块尚未被使用的内存上,我们将从 “memorySum” 的首地址出发,后面的12个字节的空间拿给pSum数组使用,再把 “pSum” 后面的20个字节的空间拿给 “pChar” 使用,然后只需要释放这块缓冲区空间即可,这就是内存的综合管理。

四.string类型

1.创建string

这里需要包含头文件 <string> ,注意这里跟C语言中的 <string.h> 是不一样的。

int main()
{
	//如果没有using namespace std,那么就需要如下表示:
	std::string str;
	//不初始化
	string str1;
	str1 = "I Love C++";
	//初始化
	string str2 = "I Love C++";
	//通过另一个字符串创建
	string str3 = str1;
	string str4(str2);
}

2.string基本操作

(1)赋值拷贝

直接使用等号,十分方便!

int main()
{
	string str1 = "one";
	string str2 = "two";
	string str3 = str1;
}

(2)连接

有两种方法,一种是直接用 “+” ,一种是调用函数。

int main()
{
	string str1 = "one";
	string str2 = "two";
	string str3 = str1 + str2;
	string str4 = str1.append(str2);
}

(3)比较

还是有两种方式,一种是直接比,一种是使用函数。

int main()
{
	string str1 = "one";
	string str2 = "two";
	if (str1 > str2)
	{
		cout << "str1比较大"<<endl;
	}
	else if (str1 < str2)
	{
		cout << "str2比较大"<<endl;
	}
	else
	{
		cout << "一样大"<<endl;
	}
	if (str1.compare(str2) == 1)
	{
		cout << "str1比较大" << endl;
	}
	else if (str1.compare(str2) == -1)
	{
		cout << "str2比较大" << endl;
	}
	else
	{
		cout << "一样大" << endl;
	}
}

3.C语言的字符串跟C++的string有何区别

string实际上是C++里的自定义类型,而且string是没有记录‘\0’的,字符则以其作为字符串的结尾。C++的string不是我们所理解的char*类型,因此不能使用C语言里的字符处理函数,想要使用,必须先把string转化为char*类型,下面两种方法都能实现:

int main()
{
	string str1 = "one";
	const char* str = str1.c_str();
	const char* strr = str1.data();
}

这种方式在用C++封装图形界面时挺常见的。

4.其他有意思的操作

这里就贴代码啦,自己瞎玩哈哈哈。

int main()
{
	string str1 = "one";
	//empty,size 万金油函数
	if (str1.empty()) cout << "为空";
	else cout << "不为空";
	cout << endl << str1.size();
	//to_string函数,跟c#里面的ToString有点像
	string str2 = to_string(123);
	//C语言可以用atoi函数,刷题有碰到
}

最后再附上查找这些函数的链接,方便查找~

basic_string 类https://docs.microsoft.com/zh-cn/cpp/standard-library/basic-string-class?view=msvc-170今天的整理就到这里了,继续努力!!!

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值