const就类似与一个保镖一个承诺,用于保护变量,他的优点有很多。
int main()
{
const int a = 5;
a = 2;
std::cin.get();
}
在这个代码中,我们是不能修改a的变量值的,因为加了const进行了保护。加了const意味着你的a已经变成常量了,而不是变量。
//可以正常运行
int main()
{
const int age = 5;
int* a = new int;
*a = 2;
std::cout << *a << std::endl;
std::cin.get();
}
//const在int前
int main()
{
const int MAX_AGE = 5;
const int* a = new int;
int const * a = new int;//和前面一样
*a = 2; //逆向引用失败,因为我们在前面加了const来保护a的值
a = (int*)&MAX_AGE;//可以改变指针a指向
std::cout << *a << std::endl;
std::cin.get();
}
//const在int后
int main()
{
const int MAX_AGE = 5;
int* const a = new int;
*a = 2; //可以逆向引用
a = (int*)&MAX_AGE; //不能改变指针的指向
std::cout << *a << std::endl;
std::cin.get();
}
const添加在int类型前保护的是变量的值,但是可以改变指针的指向,我们只是不能改变指针指向的内容。const添加在int类型后保护的是指针,和前面刚好相反。这里的关键在于const是加在*之前还是之后,如果想让指针本身变成常量,不能重新分配指针指向,那就加在*之后变量名之前。
int main()
{
const int MAX_AGE = 5;
const int* const a = new int;
//都不能修改
*a = 2;
a = (int*)&MAX_AGE;
std::cout << *a << std::endl;
std::cin.get();
}
如果是前后都加了const那么就都不能修改。
为了更好的理解const在函数中的作用,也就是const 的第三种用法,他和变量无关,而是在方法名之后(只在类中生效)
一、
class Entity
{
private:
int m_x, m_y;
public:
int GetX() const
{
//m_x= 2;error
return m_x;
}
};
二、
class Entity
{
private:
int* m_x, m_y;
public:
const int* const GetX() const //指针、指针指向内容、Entity都不能修改
{
return m_x;
}
int SetX(int x)
{
m_x = x;
}
};
三、
class Entity
{
private:
int m_x, m_y;
public:
int GetX() const //(1)当这里的cosnt删掉后你会发现后面的e.GetX会报错
{
return m_x;
}
int SetX(int x)
{
m_x = x;
}
};
void PrintEntity(const Entity& e)
{
std::count << e.GetX << std::endl;
}
一:这个方法不会修改任何的实际类,所以在GerX()不能修改Entity成员变量,我们只能读不能修改。
在二中:需要注意的是int* m_x, m_y;这里只有m_x是指针,m_y还是int。同时他是三个const超级保镖,所以他非常安全啥都改不了。
三、在三种我们可以发现(1)处的const去了之后后面的e.GetX会报错。这个是因为GetX已经不能保证他不会写入Entity类了,没有保镖保护了,现在可以不仅仅可以读而且可以写了
mutable其实就是反转了const的意思。
#include <string>
class Entity
{
private:
std::string m_Name;
mutable int m_DebugCount = 0;
public:
const std::string& GetName() const
{
m_DebugCount++; // 这里修改是允许的,因为m_DebugCount是mutable的
return m_Name; // 注意这里返回的是m_Name,而不是name
}
// ... 可能还有其他成员函数和构造函数等 ...
};