一、const与函数
1、如果参数是指针,且仅作输入用,则应在参数类型前面加const,以防止该指针在函数体内被意外修改
如:MyString 类的拷贝函数之一 MyString::MyString(const char *);
MyString::MyString(const char *sz)
{
m_len = strlen(sz);
m_data = new char[m_len + 1];
strcpy(m_data, sz);
}
2、如果输入参数以值传递方式传递对象,则宜改为“const &”方法传递,这样可以省去临时对象的构造和析构过程,从而提高效率
如:MyString类的“=”操作符重载函数:MyString& MyString::operator=(const MyString &str);
MyString& MyString::operator=(const MyString &str)
{
if(m_data != NULL)
{
delete []m_data;
}
m_len = strlen(str.m_data);
m_data = new char[m_len + 1];
strcpy(m_data, str.m_data);
return *this;
}
3、常成员函数(可被普通对象和const对象调用)
如:MyString 类内的打印方法:void MyString::display() const,以及get方法
void MyString::display() const
{
cout << "str:" << m_data << endl;
}
注:任何不修改成员数据的函数最好都声明成常成员函数,用const修饰的函数在声明和定义时都要加const,所以构造函数和析构函数都不能为const(它们必定修改对象的值);
4、const修饰类对象
const修饰的对象只能调用const成员函数
如:MyString类的const变量只可调用void MyString::display() const以及get方法
int main(void)
{
const MyString str("hello world");
str.display(); //hello world
return 0;
}
二、const与类成员数据
1、const修饰类成员数据
首先需要明确的是:const数据成员只在某个对象生存期内是常量,而对于整个类而言确是可变的,因为一个类可以实例多个对象,不同的对象其const值可以不同。
//类内const成员:const int age;
//类内构造函数:
Person(int a,int b):age(a)
{
height = b;
}
int main(void)
{
Person p1(10,20); // age 10
Person p2(100,200); // age 100
return 0;
}
注:const数据成员在每个对象的内存中分配内存,const修饰的数据成员的生命周期是类对象的声明周期,切记不能在类声明中初始化const数据成员
2、const的例外
要使某个成员变量在const对象中可以被修改,有两种方式:
(1) 把常函数中隐含的this指针强制转换成非const
注:C++是强类型语言,一般情况下不支持强制类型转换
void Person::fun() const
{
((Person*)this)->age = 50;
}
(2)更为常用的规范做法:把希望可被改变的数据成员声明为mutable
//类内声明时:mutable int age;
//在常函数内可直接更改age的值
void Person::fun() const
{
this->age = 50;
}
三、const与mutable的区别
首先:mutable的中文意思是“可变的,易变的”,跟constant(既C++中的const)是反义词。
1、const所修饰的函数中,要有编译器负责保护类中的成员函数不被修改;而相对地,mutable则是用来修饰类的成员变量的,让该变量在const修饰的常成员函数中可以被修改
2、const修饰的函数只能是类的成员函数(保护this指针不被恶意修改);mutable修饰的变量只能是类的成员变量。
3、在C++中,mutable也是为了突破const的限制而设置的。被mutable修饰的变量,将永远处于可变的状态,即使在一个const修饰的常成员函数中。