一、int const *a, const int *a, int * const a, const int *const a的异同
具体看const修饰的是什么,如果是地址则地址无法改变,如果是int或者指针内容,则显然内容无法改变
关于const的点滴补充:
1、const 对象的地址只能赋值给指向const 对象的指针
2、指向const 对象的指针可以 被赋以 一个非const 对象的地址
3、指向const 得指针常被用作函数的形式参数,保证被传递给函数的实际对象在函数得实际对象在 函数中不会被修改(所谓的this指针就是在每个成员函数中隐式地存在一个T * const this的指针, 指向每一个不同的对象实例的内容)
4、常量在定义后就不能被修改,所以它必须被初始化。未初始化的常量定义将导致编译错误(上面 都 是在说明const得问题,所以没有赋值,实际语句中要赋值的)
小结:
const是向左结合的,故const int 和int const 其实是一个意思;
const 如果在*的左边,如const int* p = ...; 那么p所指向的内容是常量,指针本身是可以改变的;
const 如果在*的右边,如int* const p = ...; 那么p这个指针本身是常量,但内容是可以改变的;
#include<iostream>
#include<map>
#include<vector>
#include<set>
#include<queue>
#include<stack>
using namespace std;
const int k = 100;
int init = 0;
int main()
{
int const *a = &k;//内容不可变,即(*a)为常量不能变且只能初始化为常量的地址 ,但是地址(a)可以变,可以指向变量或常量地址
int n = 200;
const int nn = 200;
//(*a) = n;编译错误
(a)=&n;
cout<<(*a)<<endl;
int *const b = &init;//内容可变,即(*b)可变,但地址(b)不可变,且必须要初始化地址,(*b)可以为变量或常量
//b = &n;编译错误
(*b) = n;
cout<<(*b)<<endl;
const int *c;//与a相同
const int *const d = &init;//地址内容均不能改变
system("pause");
return 0;
}
参考来源:http://bbs.csdn.net/topics/310124559
补充内容:
关于const的成员变量和成员函数
有const修饰的对象即为常量对象,顾名思义就是不允许自身或他人修改其内部内容,而函数就存在修改自身或他人内容的可能,因此:
1、非常量对象可以调用非常量成员函数(废话)
2、非常量对象可以调用常量成员函数
3、常量对象可以调用常量成员函数
4、常量对象不允许调用非常量成员函数,即使该成员函数不修改任何内容
5、常量成员函数无法修改任何对象,因此构造函数必须为非常量函数,另构造函数可以初始化常量对象
总之,常量(const)就是不可以受内因和外因改变,一旦定义就需要初始化为固定值无法再改变。
二、inline内联函数小观
摘要:
1、 inline是一种用于函数实现的关键字,而非声明
2、 inline 的出现主要是为了取代表达式的宏定义,使其不只是简单的参数替换
3、 内联函数对编译器只是一种建议,编译器可以根据具体环境拒绝使用内联
4、 可以使用inline函数完全取代表达式形式的宏定义,它能提高更高的效率(没有参数压栈、代码生成)函数的代码被放入符号表中,在使用时直接进行替换,(像宏一样展开),没有了调用的开销,效率也很高。
5、 编译器会将类中符合条件的函数自动内联化
6、 注意事项:
内联函数大多直接定义到头文件中,主要为了避免不同文件之间的函数重名冲突
适用范围:
内联适用于短小精悍的函数,多用于类的存取函数(getter、setter)
不宜使用:
函数实现代码过长或者其中循环时间超过调用时间
参考来源:
http://www.cnblogs.com/berry/articles/1582702.html
http://baike.baidu.com/view/1365655.htm?fr=aladdin
三、关于程序的内存分配(堆区、栈区、静态存储区、常量存储区、程序代码区)
http://blog.csdn.net/benny5609/article/details/2217258
http://blog.csdn.net/jack__h/article/details/5419856
四、enum枚举类型
枚举(enum关键字)
首先要了解到枚举是一种类型定义,其内部元素均为整形,然后注意事项如下:
1、 各枚举内容不能重复,即枚举名和内容均不允许重名
2、 定义枚举对象时前面加上enum关键字
3、 枚举内容会依次递增,可通过在定义处赋值更改
枚举较宏定义的好处:
1、 可以自动递增为枚举元素赋初值
2、 可以形成数据集合
注:sizeof(枚举类型名)=4,因为其内部元素均为整形
typedef enum day1{q,w,e,r,t,y,u}day;
enum day2{q1,w1,e1,r1,t1,y1,u1};
aa a, b;
a.add_d();
day kk = q;
enum day2 ll = w1;
cout<<sizeof(day)<<' '<<kk<<endl;
参考来源: http://blog.sina.com.cn/s/blog_615ec1630101kr5d.html
五、指针函数和函数指针
指针函数:其本身为一个函数,具体定义为 [类型] *fun ([参数列表]),例如:int *address(node x)。显然这是一个函数,只不过其返回值为指针的地址罢了,正因为如此, 所以返回值多为int。
函数指针:其本身为一个指针,具体定义为 [类型] (*fun)([参数列表]), 例如:int (*ptr) (node x)。这是一个存放函数地址的指针,由于括号比*优先级高,所以避免fun与 参数列表结合形成指针函数,主要用于回调函数。
注:回调函数,某函数地址作为形参传入另一函数,在特定情况下进行触发并产生作用,就好像是一个中断处理函数,系统在符合你设定的条件时自动调用。之所以称之为回调函数,是因为被调用函数是以地址的形式作为当前函数的实参传递进来的,类似于中断号,当需要调用时通过该地址找到函数入口,当然,这样被调用函数的参数也得随着其地址一同传入调用它的函数实参中或者由函数内部赋予,总之只要能理解中断的内部机制,就能很轻松地明白回调函数是怎么回事
参考来源:
http://www.cnblogs.com/gmh915/archive/2010/06/11/1756067.html
http://blog.csdn.net/ac_lion/article/details/24413313(这位美女粉了我,正好互粉一下)
六、关于c++的强制转换static_cast\dynamic_cast\reinterpret_cast\const_cast的区别及应用
http://riddickbryant.iteye.com/blog/547361
七、C++引用
C++中的引用其实质为一个指针常量,即int *const ptr,它的特殊之处在于使用时能够由编译器自动进行解引用,请看如下例子
int i = 10; // A simple integer variable
int &k = i; //k为i的引用
int *const j = &i; // A Reference to the variable i
(*j)++; // Incrementing j. Since reference variables are
// automatically dereferenced by compiler
// check by printing values of i and j
cout<< i << ' ' << *j << ' ' << k <<endl; // should print 11 11 11
cout<< &i << ' ' << j << ' ' << &k <<endl;//应当均输出i的地址,其中j值为i的地址,定义中可看出,
//而引用k实质上被编译器自动解引用,即&(*k),&*抵消故实质和j是一样的
// A * is appended before j because it used to be reference variable
// and it should get automatically dereferenced.
system("pause");
return 0;
这里的int *const j = &i就等同于 int &j = i,在引用的输出语句中,j自动被编译器解引用变为(*j),故结果仍然为j所值地址的内容,即i。
参考来源:
http://blog.csdn.net/webscaler/article/details/6577429