<pre name="code" class="cpp">
int a =5;
const int &b = a;
//b = 3; //无效
a=7; //有效
const int ci=1024;
const int &ri = ci;
// ri = 2;
const int &r2 = ci;
int i=3;
const int &r1 = i;
const int &r22 = 5;
const int &r3 = r1*2;
// int &r4 = r1*4; // //错误,改为const int &r4 = r1*4
double dval = 3.14;
// int &r = dval; //错误
const int &r = dval;//等价于 const int temp = dval;const int &r=temp;
<pre name="code" class="cpp">
int a =5;
const int &b = a;
//b = 3; //无效
a=7; //有效
const int ci=1024;
const int &ri = ci;
// ri = 2;
const int &r2 = ci;
int i=3;
const int &r1 = i;
const int &r22 = 5;
const int &r3 = r1*2;
// int &r4 = r1*4; // //错误,改为const int &r4 = r1*4
double dval = 3.14;
// int &r = dval; //错误
const int &r = dval;//等价于 const int temp = dval;const int &r=temp;
const放在函数形参里面
可以防止函数修改参数
const放在函数后面表示什么?
表示这个函数是一个只读函数,既不能更改成员的值,也不能调用成员函数修改成员的值。 只能调用const函数。
简单点说,就是防止修改掉用它的对象。
//需要再研究一下数据存储 弄明白各个区域的作用。下面跟着的博客讲述内存分配很详细。
const char *p = "aaaa"; //p指向常量区
p[2]='d'; //错误。 只读的常量去
const char str1[] = "abc";
const char *p1 = str1; //
p1[2] = 'd'; //无效。
char str2[] = "abc";
char *p2 = str2; //str在栈上拷贝了一份 指针指向栈,不指向常量区。
p2[2] = 'd'; //有效。
堆、栈、自由存储区、全局/静态存储区和常量存储区
获取数组元素个数可以使用:
sizeof(arrStuInfo)/sizeof(studentInfo)
sizeof(arrStuInfo)/sizeof(arrStuInfo[0])
如果在本函数内部的话用sizeof可以做到
如果你想将此数组作为参数传递给另外的函数的话,必须用变量记录它的大小,因为在传递过程中,数组已经退化成为了指针。
如果你想将此数组作为参数传递给另外的函数的话,必须用变量记录它的大小,因为在传递过程中,数组已经退化成为了指针。
动态分配内存
calloc 分配一定长度的内存空间,并且把这块内存清零。
int *qArr = calloc(10, sizeof(int)); //等价于 int *qArr = realloc(NULL, 10*sizeof(int));
对qArr重新分配内存,并保留原qArr的值
qArr = realloc(qArr, 20*sizeof(int));
memset(qArr, 0, sizeof(int)*10); //按照字节来设置, 把所有字节设置为0
memset(qArr,1, sizeof(int)*2); // 前两个字节为, 00000001 00000001 后面是00000000 000000000……
函数指针
int maxValue( int num1, int num2){}
int (*pFunc)( int num1, int num2); //定义一个函数指针
pFunc = maxValue;
指针数组
含义
指针数组中的元素亦可以表示为“*(*(ptr_array+i))”。又因为“()”的优先级较“*”高,且“*”是右结合的,因此可以写作**(ptr_array+i)。
由于数组元素均为指针,因此ptr_array[i]是指第i+1个元素的指针。
与二维数组对比
二维
数组:如char string_1[10][10]只要定义了一个二维
数组,无论赋不赋值,系统都会给他分配相应空间,而且该空间一定是连续的。其每个元素表示一个字符。我们可以通过制定下标对其元素进行修改。
char a[3][8]={"gain","much","strong"};
char *n[3]={"gain","much","strong"};
他们在内存的存储方式分别如右图所示,可见,系统给
数组a分配了
3×8的空间,而给n分配的空间则取决于具体字符串的长度。
此外,系统分配给a的空间是连续的,而给n分配的空间则不一定连续。
由此可见,相比于比二维字符
数组,
指针数组有明显的优点:一是指针数组中每个元素所指的字符串不必限制在相同的字符长度;二是访问指针数组中的一个元素是用指针间接进行的,效率比下标方式要高。 但是二维字符
数组却可以通过下标很方便的修改某一元素的值,而
指针数组却无法这么做。
函数指针数组
int (*pFunc[6])(int m, int n) = {max,min,sum,dev,sub,mul};
以前一直不理解为什么要使用回调函数,想当然的以为根本不需要一个函数指针,直接使用函数就可以了。 程序设计要高内聚,低耦合,每一个模块只能够实现固定的功能,所以如果要使用其他模块的函数的时候,不能够定义一个对象来调用函数,这样的设计是不正确的。 但是其他模块可以暴露一个函数出来,调用它的指针,这样来实现,这就是函数回调。
例子
int max( int num1, int num2){//max,min, sun, reduce, mul, division 自己定义函数
return num1>num2?num1:num2;
}
int (* getPFunc(void))(int ,int ){ //int (* )(int ,int ) 这是定义一个函数指针, 里面定义的函数getPFunc(void)的返回值是函数指针
</span>
int num = 0;
scanf("%d",&num);
int (*pFunArray[6])(int ,int) = {max,min, sun, reduce, mul, division };
return pFunArray[num];
}
int getValue(int num1, int num2, int(*pFunc)(int ,int)){
return pFunc(num1, num2);
}
int main(int argc, const char * argv[])
{
int (*pFunc)(int ,int) = getPFunc() ;
int result = getValue(2, 5, pFunc);
C++ - 类成员初始化顺序
-- 关于类成员的初始化有两种方式
1. 构造函数的实现中
2. 定义初始化成员列表
其顺势为
1. 分配内存,调用成员变量的构造函数隐式/显示的初始化各成员数据
2. 进入类构造函数后执行构造函数内部的代码
3. 类成员变量的初始化顺序以成员在类中的声明为序, 而不管它在初始化成员列表的出现顺势。(这是因为定义的顺序是固定的, 而不同的构造函数其初始化成员列表的顺序可能不一样, 变编译器没法提供统一的工作模式)
下列情况下成员必须在初始化列表中完成初始化
1. 调用基类的非缺省构造函数
2. const类型数据成员
3. 引用类型的数据成员
标准库的一些算法sort greater less plus negate
std::plus<int> intAdd;
int sum = intAdd(10,20);
std::cout<<sum<<std::endl;
std::plus<std::string> strAdd;
std::string strsum = strAdd("a","b");
std::cout<<strsum<<std::endl;
std::negate<int> intNegate;
int num = intNegate(10);
std::cout<<num<<std::endl;
//排序 sort函数 第三个参数可以是函数指针 lanmbda函数 标准库函数对象。
std::vector<int> vec={2,1,4,5,6,7};
sort(vec.begin(), vec.end(), std::greater<int> ());
for (auto i:vec) {
std::cout<<i<<std::endl;
}
std::less<int> f;
sort(vec.begin(), vec.end(), f);
for (auto i:vec) {
std::cout<<i<<std::endl;
}