文章目录
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,因为不是通过引用来传递的。