文章目录
常量与const
1、const修饰常量和数组
使用const关键字修饰的常量是只读的,在程序运行时不能更改。const关键字可以用在类型名前,也可以用在类型说明符后。
//----------常量----------
const double RATE=0.069; //const在类型名之前
const int amount=10;
string const name="Linda"; //const在类型名之后
//----------数组----------
const int array1[2][3]={1,2,3,4,5,6};
const double array2[3]={2.1,2.3,5.6};
要注意,在定义一个命名常量时,必须用一个值来进行初始化。它不能先定义,然后再通过赋值语句来进行赋值。
const double RATE; //非法
RATE=2.5; //非法
2、const修饰指针变量
1、顶层const(top-level const)
指针常量,指针本身是常量。声明时必须初始化,一旦声明完成指针本身的值(指针存储的地址值)就不能再改变,即指针不能再指向除此地址之外的其他任何东西。
格式:const在指针符号*后面,即:*const 。
int c=8;
int* const pc=&c; //顶层指针,指针本身是一个常量,不可改变。
2、底层const(low-level const)
==指向常量的指针,指针指向的对象是一个常量。==指针指向的数据不能改变,但指针本身可以改变。
格式:const放在类型名前后都可以。
int const a=10; //常量a
const int b=5; //常量b
const int* pa=&a; //底层const,指针pa指向的内容是常量,不可改变。
int const*pb=&b; //底层const,const和数据类型可以互换位置。
3、区分
这个地方比较容易搞混,这篇文章的解释非常形象细致。
https://blog.csdn.net/u011333734/article/details/81294043
以下是摘抄的文章内容:
根据从内到外,由近到远读符号的规则
int a = 1;
int b = 2;
const int* p1 = &a;
int* const p2 = &a;
p1依次解读为:p1是个指针(*),指向一个int型对象(int),该对象是个常量(const)。 因此这是一个底层cosnt。
p2依次解读为:p2是个常量(const),p2是个指针(*),指向一个int对象(int)。 因此这是一个顶层const。
3、const修饰引用变量
使用cons也可以修饰引用,被修饰的引用为常引用,不能通过该引用变量来修改所引用的对象。
格式:
int d=6;
const int &pd=d; //const关键字和数据类型名的顺序可以交换
int const &pe=d;
pd=7; //非法
函数与const
1、const修饰函数参数
const修饰函数参数的情况
1、引用传递:函数的形参为引用变量。由于引用变量是另一个变量的别名,对引用变量做出的任何更改实际上都是对它所引用的变量内存位置中存储数据的更改。当函数因为某种原因需要使用引用变量作为形参来减小拷贝开销时,如果对引用参数加上const修饰符,就可以防止修改对象的值,达到了保护对象和减小开销的两个目的。
double Num(const int &x)
2、指针传递:给指针参数加上顶层const可以防止指针指向被篡改,加上const关键字可以防止指向对象被篡改。
void fun(const char * s1, char * s2)
当实参按值传递给形参时,只会传递实参值的副本,函数体内对形参的改变不会影响到实参。因此按值传参的时候不需要const关键字的修饰。
要注意:虽然常量的地址只能传递给指向const的指针,但是,指向const的指针也可以接收非常量项目的地址。
2、const修饰函数返回值
1、返回指针
给返回值为指针的函数的返回值加 const 修饰,那么函数返回的指针就不能被修改,且返回值只能被赋给同样有const 修饰的同类型指针。
//------不使用const关键字修饰------
string* getName()
{
string name="Lucy";
string* n=&name;
return n;
}
int main()
{
string *x=getName();
cout<<*x;
return 0;
}
//------使用const关键字修饰------
const string* getName()
{
string name="Lucy";
string* n=&name;
return n;
}
int main()
{
const string *x=getName();
cout<<*x;
return 0;
}
2、返回引用
给返回值为引用的函数的返回值加 const 修饰,使得函数调用表达式不能作为左值。
//------不使用const关键字修饰------
class Test {
private:
int a;
public:
Test()
{//a的值初始化为0
a=0;
}
int & getA(){
return a;
}
void show()
{
cout<<a<<endl;
}
};
int main()
{
Test a;
a.show(); //此时a的值为0
a.getA()=100;//尝试通过返回值修改a的初始值
a.show(); //此时a的值已经被修改
}
//------使用const关键字修饰------
class Test {
private:
int a;
public:
Test()
{//a的值初始化为0
a=0;
}
const int & getA(){
return a;
}
void show()
{
cout<<a<<endl;
}
};
int main()
{
Test a;
a.show(); //此时a的值为0
//a.getA()=100;//尝试通过返回值修改a的初始值,但无法修改成功
a.show();
}
报错,无法修改:
类与const
1、const修饰成员变量
格式与const修饰一般常量时相同。
在类内部使用const关键字来声明const数据成员,那么const数据成员的值不能被修改。初始化时只能通过构造函数初始化列表初始化。不能在构造函数里面初始化。
class Square
{
private:
const int length;
int width;
public:
Square():length(1) //只能在构造函数初始化列表中初始化
{
width=0;
}
void show(){cout<<length<<'\n'<<width;}
};
2、const修饰成员函数
指定常量成员函数,告诉编译器该函数不应更改对象中的任何数据字段的值。
格式:将 const 关键字放在函数头的末尾。
int getArea() const
{
//width=5;//错误,不可以修改
return length*width;
}
注:
1、非const对象可以调用const成员函数或者非const成员函数。
2、const对象只能调用const成员函数,若直接调用非const成员函数编译器会报错。
3、构造与析构函数不能定义为const成员函数,因为构造函数和析构函数会对对象做修改
class Square
{
private:
const int length;
int width;
public:
Square():length(1) //只能在构造函数初始化列表中初始化
{
width=1;
}
int getArea() const
{
return length*width;
}
int getPerimeter()
{
return (length+width)*2;
}
};
int main()
{
Square s;
const Square s1;
cout<<s.getArea(); //非const对象可以调用const成员函数
cout<<s.getPerimeter(); //非const对象也可以调用非const成员函数
cout<<s1.getArea(); //const对象只能调用const成员函数
cout<<s1.getPerimeter(); //const对象不能调用非const成员函数,编译报错
}