1:函数中参数缺省问题
函数声明部分:
void mytest(std::string &hash, float &Deviation, std::vector<std::string> reference=std::vector<std::string> ());
注意在定义部分是没有给缺省值!
函数定义部分:
mytest(std::string &hash, float &Deviation, std::vector<std::string> reference)
{
}
注意:
vector的初始化方式有以下几种,所以初始化的右值可以多种方式:
vector<string> svec(10); // 10个元素,每个都是空string对象
/vector<string> svec(10, "hi!");
在函数缺省参数的使用时候上述两种是可用的,而下述两种是不可用的(但是这两种也是vector的初始化方法)。
ector<string> articles = {"a", "an", "the"};
vector<string> v1{"a", "an", "the"}; // 列表初始化
2:类中成员不能是该类的对象作为成员
从对象构造函数的角度来说:
因为如果类包含自身类的对象,存在无限初始化的问题。
构造一个类的对象是,先构造成员变量,然后再调用自身的构造函数,如果类包含自身的的对象,那么在调用构造函数之前,需要先构造自身类的对象。而构造自身类的对象时,又得先构造自身的对象,然后调用其构造函数。。。。这样便会无限循环。
从实例化对象分配空间来说:
当用实例化一个类的对象时,编译器会根据类的定义来分配相应的存储空间。也就是说,在创建对象前,一定要有完整的类定义,这样编译器才能正确的计算所需空间。
如果是下面的代码:
class Screen{
Screen sc; //error, 'sc' uses undefined class 'Screen'
//etc...
};
上述代码中,由于Screen还没有定义结束,在内部定义一个Screen类型的对象时,编译器无法知道应该为sc分配多少空间,因此会报注释中的错误。
但是可以,在类定义时,指向自身类型的指针或引用作为数据成员则没有问题。这是因为指针和引用所占存储空间大小与类型无关,所以编译器可以计算分配空间。
class Screen{
Screen *sc1; //ok
Screen &sc2; //ok
};
3:多维数组的访问和赋值问题
char b[2][3][3]={'1','2','a','b','c','d','e','f','g','h','i','k','L','M','N'};
char (*p)[3][3] = b;
char (*r)[3] = b[0];
char *t = b[0][0];
char u = b[0][2][2];
// printf("%x\n",p);
std::cout<<*p<<"\t"<<p<<"\t"<<b<<std::endl;//都是数组名
std::cout<<*r<<"\t"<<*t<<std::endl;
std::cout<<u<<"\t"<<&u<<std::endl;
4:检测系统中浮点数0.0的位模式是否与整型数0的位模式相同
printf("sizeof double is:%d\n",sizeof(double));
printf("sizeof int is:%d\n",sizeof( int ));
double d0=0.0;
int i0[2]={0,0};
if(*(double*)i0==d0){
puts("is the same!");
}
else {
puts("not the same!");
}
从结果看出,是相同的。
5:数组参数的地址和数组参数的第一个元素的地址不同
void fun1(char ca[])
{
printf("char ca:\n");
printf("%x\n", &ca);
printf("%x\n", &(ca[0]));
printf("%x\n", &(ca[1]));
}
void fun2(char* pa)
{
printf("char* pa:\n");
printf("%x\n", &pa);//printf("%#x\n", &pa);打印的方式不同而已,多一个0X
printf("%x\n", &(pa[0]));
printf("%x\n", &(pa[1]));
printf("%x\n", ++pa);
}
void main()
{
char test[] = "helloworld";
fun1(test);
fun2(test);
printf("test:\n");
printf("%x\n", &test);
printf("%x\n", &(test[0]));
printf("%x\n", &(test[1]));
}
从上述的运行结果,发现数组参数的地址和数组参数的第一个元素的地址不一样,这是为什么呢?
这是因为在fun1()的第二行,打印的内容为”&ca“,而&ca的实际意义为ca的地址,即指向ca的指针。在函数内部,ca本身就是一个指向数组第一个元素的指针,无需取ca的地址,直接打印ca的值即可,取得ca的地址,实际上是该指针的地址。将第二行的语句替换为:printf(“%x\n”, ca)即可。
6:数组指针和指针数组的区别
1)数组指针(也称行指针)
定义 int (*p)[n];
括号()优先级高,首先说明p是一个指针,指向一个整型的一维数组,这个一维数组的长度是n,也可以说是p的步长。也就是说执行p+1时,p要跨过n个整型数据的长度。
如要将二维数组赋给一指针,应这样赋值:
int a[3][4]={1,2,3,4,5,6,7,8,9,10,11};
int (*p)[4]; //该语句是定义一个数组指针,指向含4个元素的一维数组。
p=a; //将该二维数组的首地址赋给p,也就是a[0]或&a[0][0]
std::cout<<*p<<"\t"<<&a<<"\t"<<p[0][2]<<std::endl;
p++;//该语句执行过后,也就是p=p+1;p跨过行a[0][]指向了行a[1][]
std::cout<<*p<<"\t"<<&a<<"\t"<<p[0][2]<<std::endl;
所以数组指针也称指向一维数组的指针,亦称行指针。
2)指针数组
定义 int *p[n];
[]优先级高,先与p结合成为一个数组,再由int*说明这是一个整型指针数组,它有n个指针类型的数组元素。这里执行p+1是错误的,这样赋值也是错误的:p=a;因为p是个不可知的表示,只存在p[0]、p[1]、p[2]…p[n-1],而且它们分别是指针变量可以用来存放变量地址。但可以这样 *p=a; 这里*p表示指针数组第一个元素的值,a的首地址的值。
如要将二维数组赋给一指针数组:
int *p[3];
int a[3][4];
for(i=0;i<3;i++)
p[i]=a[i];
这里int *p[3] 表示一个一维数组内存放着三个指针变量,分别是p[0]、p[1]、p[2]
所以要分别赋值。
这样两者的区别就豁然开朗了,数组指针只是一个指针变量,似乎是C语言里专门用来指向二维数组的,它占有内存中一个指针的存储空间。指针数组是多个指针变量,以数组形式存在内存当中,占有多个指针的存储空间。
还需要说明的一点就是,同时用来指向二维数组时,其引用和用数组名引用都是一样的。
比如要表示数组中i行j列一个元素:
*(p[i]+j)、*(*(p+i)+j)、(*(p+i))[j]、p[i][j]
例如:
std::cout<<*(p[0]+2)<<"\t"<<*(*(p+0)+2)<<"\t"<<(*(p+0))[2]<<"\t"<<p[0][2]<<std::endl;
都是输出数字7,都是表示p[0][2]
ps:
优先级:()>[]>*
7:
8:
【待补充】