0
点赞
收藏
分享

微信扫一扫

Cherno C++系列笔记9——P34~P35 const

small_Sun 2022-03-30 阅读 26
c++

文章目录

1.P34 const关键字

参考: 视频 笔记

1.1.普通常量、常量指针、指针常量

1.1.1.普通常量

const int MAX_AGE=90;
int* a=new int;
*a=2;
a = (int*)& MAX_AGE;

1.1.2.常量指针

现在我们开始添加const, const int *意味着不能修改该指针指向的内容,即这个指针指向的内存中的数据是不能更改的。

const int MAX_AGE=90;
const int* a = new int;
*a=2;//错误
std::cout << *a << std::endl;
a = (int*)& MAX_AGE;

我们不能解引用这个指针然后改变a的值,但我们可以读取a,逆向引用并打印它。也可以尝试改变a本身,让a指向MAX_AGE。但是不能改变指针指向的内容。

另外注意:下面两种写法意思一致,记忆方法就是只要const在*前面,那么就是常量指针,也就是指针指向的数据不能改变。

const int* a = new int;
int const* a=new int;

1.1.3.指针常量

第二种使用const的方法是把它放在*号以后。

 int* const a = new int;

它的作用刚好相反,我们可以改变指针指向的内容,但不能把实际的指针本身重新赋值,指向别的变量。

1.1.4.const int* const

我们也可以写两个,这意味着即不能改变指针指向的内容,也不能改变指针本身让它指向别的地址。

1.2.在类中的const

1.2.1.类中的常量方法

如下代码,把const放在方法名GetX的右边,在参数列表之后。这意味该方法不会修改任何实际的类,也不能修改类成员变量。若让m_X=2则会报错。

class Entity
{
private:
	int m_x, m_y; 
public:
	 int GetX() const
	{
		return m_x;
	}
};

在这里插入图片描述

1.2.2.类作为形参进行常量引用传递

创建Entity实例e,有一个PrintEntity函数可以访问GetX方法,传入的是Entity变量。

void PrintEntity(Entity e)
{
	std::cout << e.GetX() << std::endl;
}

我们希望可以通过常量引用传递这个参数,因为不想再次复制Entity类(需要分配空间)。首先引用就类似于Entity* const即指针常量,也就是引用谁是不能改变的。再在前面加一个const,就相当于变成了const Entity* const,也就是引用的变量的值也不能改变。

void PrintEntity(const Entity& e)
{
	std::cout << e.GetX() << std::endl;
}

如果将GetX方法中的const去掉,就不能调用GetX函数,因为GetX函数不能保证不会对Entity类的内容做出修改。常对象只能调用常函数

在这里插入图片描述
我们没有直接修改Entity,但是调用了一个方法它可以修改Entity,这是不被允许的。所以需要将方法标记为const,这意味当我调用const的Entity时,可以调用任何const函数。

总之,只要把方法GetX标为const,它们就不能修改类。如果该方法没有标记为const,则在有常量引用的情况下,就无法使用GetX方法。
在这里插入图片描述

1.2.3.mutable关键字

在某些情况下,我们将方法标记为const,但又需要修改变量var。可以使用C++的关键词mutable,我们把var变量设为mutable,这意味着它是可以改变的。
在这里插入图片描述

2.P35 mutable关键字

参考: 视频 笔记

2.1.类中配合const函数使用mutable(绝大多数情况)

结合前面讲的const关键字看如下代码。

#include<iostream>
#include<string>

class Entity
{
private:
	std::string m_Name;
public:
	const std::string& GetName() const
	{
		return m_Name;
	}
};

int main()
{
	const Entity e;
	e.GetName();
	std::cin.get();
}

假设现在为了调试,看程序调用了类中的方法多少次,我们设置一个变量为m_DebugCout初始化为0,来统计调用的次数。

在这里插入图片描述
但不能这样做,只有去掉GetName后的const才行。但是主函数中又不能调用GetName了,因为这个GetName应该是const的。

在这里插入图片描述
我们把m_DebugCout参数标记为mutable就好了。因为标记类成员为mutable,意味着类中的const方法可以修改这个成员。

在这里插入图片描述

2.2.配合lambda表达式实现值传递的传入参数修改(很少使用)

2.2.1.lambda表达式的参数传递

lambda就像一个一次性的小函数,可以写出来并赋值给一个变量,我们可以像调用其他函数一样调用它。

int main()
{
	int x = 8;
	auto f = [&]() //auto f = [x](),auto f = [=](),
	{
		std::cout << x << std::endl;
	};
	f();

	std::cin.get();
}

[&]表示对所有变量进行引用传递,[=]表示对所有的变量进行按值传递,[x]这样表示仅仅对x进行传递而且是值传递。

2.2.2.mutable的使用

若把lambda式子中输出x改变x++,我们就不能进行按值传递。
在这里插入图片描述这种情况下我们可以赋值给另外的变量y,然后修改这个变量。相当于创建一个局部变量,然后将x赋值给它。
在这里插入图片描述
我们还可以引入mutable关键字,auto f = [=] () mutable,这就意味通过值传递的变量x,可以被改变。注意在调用lambda之后,x的值仍为8,因为不是通过引用来传递的。

在这里插入图片描述

举报

相关推荐

0 条评论