1、指针和const修饰符
指向const的指针:
const double *cptr;cptr是一个指向const double的指针,这里不需要初始化是因为cptr可以指向任何东西,但它所指的东西是不能被改变的。
举个例子:const int* p = 12; 再赋值成*p = 10;就会报错了,而p++;就不会报错;
const指针:
double d = 1.0;
double * const cptr = &d;
cptr是指向double类型的const指针,指针不可以改变,但是可以改变指针指向的值。举个例子: int *const p = 12; 再赋值成*p = 10;不会报错,而p++;就会报错;
2、一段重要的话:函数除了返回值类型外,还可以返回指针。函数不能返回指向局部栈变量的指针,这是因为在函数返回后它们是无效的,而且栈也被清理了。可返回的指针是指向堆(new)中分配的存储空间的指针或指向静态存储区(static)的指针,在函数返回后它仍然有效;
3、const用来修饰函数的参数
这个在我们编写c++工程的时候会被经常性的用到。
举个例子:
int fun(int* i);
const int a = 1;
fun(&a);
上面这段代码是有问题的,编译的时候会提示“const int*类型的实参与int*类型的形参不兼容”,这导致函数fun只能接受非const int*类型的实参,如fun函数声明为int fun(const int *),则其可以接受const int* 和int*型的实参;即const和非const类型可以赋值给const类型,而const类型不能赋值给非const类型。
在函数参数中使用常量引用也非常正要,看下面的例子:
void fun(int &i){}
f(1);//编译错误
调用f(1)会产生一个编译错误,因为编译器必须首先建立一个引用。即编译器为一个int类型分派临时存储单元,同时将其初始化为1并为其产生一个地址和引用捆绑在一起,存储的内容是常量,故实参是const int类型,赋值给int的非const引用,所以会产生错误。
4、const成员函数
const成员函数不能修改调用该函数的对象;const实施在成员函数的目的,为了确保该成员函数可作用于const对象身上。const对象、指向const对象的指针或引用只能调用其const成员函数,如果尝试调用非const成员函数,则是错误的。
#include <iostream> class A { public: A() { } ~A() { } void OutA() const; void OutB(); }; void A::OutA() const { std::cout<<"OutA;"<<std::endl; } void A::OutB() { std::cout<<"OutB"<<std::endl; } int main() { const A a; a.OutA(); a.OutB(); return 0; }
上面这段代码编译会出现错误,错误的原因是因为const对象指向了非const的成员函数;
5、const数据成员
const数据成员必须在构造函数的成员初始化列表中进行初始化;
class Thing{
Thing() : value(1){}
int v;
const int value;
};
再看下面的例子:
#include <iostream> using namespace std; class A { public: A(int size) : SIZE(size) {}; private: const int SIZE; }; int main() { A a(100); }
此时的const变量属于具体的一个对象,如何在整个类中都恒定不变呢?
我们采用枚举
如下:
#include <iostream> using namespace std; class A { private: enum {SIZE = 100}; public: int array[SIZE]; }; int main() { A a; }