与不修改类对象的函数。例如:
const Screen blankScreen;
blankScreen.display(); // 对象的读操作
blankScreen.set(‘*’); // 错误:const类对象不允许修改
??C++中的常量对象,以及常量对象的指针或引用都只能调用常量成员函数。
??要声明一个const类型的类成员函数,只需要在成员函数参数列表后加上关键字const,例如:
class Screen
{
public:
char get() const;
};
在类外定义const成员函数时,还必须加上const关键字:
char Screen::get() const
{
return screen[cursor];
}
若将成员成员函数声明为const,则该函数不允许修改类的数据成员。例如:
class Screen
{
public:
int get_cursor() const {return cursor; }
int set_cursor(int intival) const { cursor = intival; }
};
在上面成员函数的定义中,get_cursor()的定义是合法的,set_cursor()的定义则非法。
值得注意的是,把一个成员函数声明为const可以保证这个成员函数不修改数据成员,但是,如果据成员是指针,则const成员函数并不能保证不修改指针指向的对象,编译器不会把这种修改检测为错误。例如:
class Name
{
public:
void setName(const string &s) const;
char *getName() const;
private:
char *m_sName;
};
void setName(const string &s) const
{
m_sName = s.c_str(); // 错误!不能修改m_sName;
for (int i = 0; i < s.size(); ++i)
m_sName[i] = s[i]; // 不是错误的
}
const成员函数可以被具有相同参数列表的非const成员函数重载,例如:
class Screen
{
public:
char get(int x,int y);
char get(int x,int y) const;
};
在这种情况下,类对象的常量性决定调用哪个函数。
const Screen cs;
Screen cc2;
char ch = cs.get(0, 0); // 调用const成员函数
ch = cs2.get(0, 0); // 调用非const成员函数
const成员函数不能修改类对象数据成员的深层解析:
调用成员函数时,通过一个名为this
的隐式参数来访问调用该函数的对象成员。例如:
Name bozai;
bozai.setName("bozai");
bozai.getName("BOZAI");
调用setName时隐式传入 this 形参,通过改变 this->m_sName 的值来改变bozai对象的m_sName。
当调用getName时,同样是隐式传入 this 形参,不过此时的 this 被 const 修饰了,所以不能通过 this 修改对象的成员了。
原文链接:https://blog.csdn.net/weixin_45773137/article/details/126297568
4.constexpr 限定符
4.1常量表达式
常量表达式:指值不会改变并且在编译过程就能得到结果的表达式;字面值、用常量表达式初始化的const对象也是常量表达式。
字面值类型:算术类型、引用和指针都属于字面值类型,自定义类、IO库,string类型则不属于字面值类型,不能被定义成constexpr;
一个对象(或表达式)是不是常量表达式由它的数据类型和初始值共同决定, 例如:
const int max_files = 20;//max_files是常量表达式
const int limit = max_files + 1; //limit是常量表达式
int staff_size = 27;//staff_size不是常量表达式
const int sz = get_size();//sz不是常责表达式
??尽管sz本身是一个常量,但它的具体值直到运行时才能获取到,所以也不是常量表达式。
4.2constexpr变量
??在一个复杂系统中,很难(几乎肯定不能)分辨一个初始值到底是不是常量表达式。当然可以定义一个const变量并把它的初始值设为我们认为的某个常量表达式,但在实际使用时,尽管要求如此却常常发现初始值并非常量表达式的情况。可以这么说,在此种情况下,对象的定义和使用根本就是两回事儿。
??C++11新标准规定,允许将变量声明为constexpr类型以便由编译器来验证变量的值是否是一个常量表达式。声明为constexpr的变量一定是一个常量,而且必须用常量表达式初始化:
constexpr int mf = 20;//20是常量表达式
constexpr int limit= mf + l;//mf + 1是常量表达式
constexpr int sz = size();//只有当size是一个constexpr函数时才是一条正确的声明语句
4.3constexpr函数
??尽管不能使用普通函数作为constexpr变量的初始值,但是正如C++ Primer6.5.2节(第214页) 将要介绍的,新标准允许定义一种特殊的constexpr函数。这种函数应该足够简单以使得编译时就可以计算其结果,这样就能用constexpr函数去初始化constexpr变量了。
constexpr函数
:指能用于常量表达式的函数,其定义方式和普通函数类型;
定义规则
:
- 函数的返回类型及所有形参类型都是字面值类型
- 函数体中只有一条return 语句
constexpr int func(int n)
{
return n;
}
int main()
{
int n=10;
const int m=10;
constexpr int i = func(10);//正确,i是一个常量表达式
constexpr int j = func(n);//错误,n不是字面值
constexpr int k = func(m+1);//正确,k是一个常量表达式
return 0;
}
由于func是constexpr函数,编译器能在程序编译时验证func函数返回的是常量表达式,如上面的j,因为n不是常量,所以会在编译期间报错,方便修正
不仅如此,对于constexpr函数,编译器会把constexpr函数的调用替换成其结果值,为了能在编译过程中随时展开,constexpr函数被隐式地指定为内联函数,关于内联函数在这篇C++内联函数博客中有详细介绍
简单的来说,如果其传入的参数可以在编译时期计算出来,那么这个函数就会产生编译时期的值,如果传入的参数如果不能在编译时期计算出来,那么constexpr修饰的函数就和普通函数一样了
————————————————
版权声明:本文为CSDN博主「倒地不起的土豆」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.cs