Q: const的用途
在C中,const的用法有定义常量,修饰函数参数,修饰函数返回值。在C++中,const还可以修饰函数的定义体,定义类中某个成员函数为恒态函数,即不改变类中的数据成员。被const修饰的东西都受到强制保护,可以预防意外的变动,能提高程序的健壮性。
Q: const和#define都能定义常量,但用const优点更多。
(1)const常量有数据类型,宏常量没有数据类型。编译器可以对前者进行类型的安全检查,后者只进行字符替换,没有类型安全检查,并且在字符替换中可能产生意料不到的错误。
(2)有些调试工具可以对const进行调试,但是不能对宏常量进行调试。const常量完全取代宏常量。
C++离港篇的const教学。
如果定义一个整型。
int x; //变量
变量名:x
存储地址: &x
存储内容: 3
如果加上 const int x;//常量
变量名:x
存储地址:&x
存储内容:3
其中const的存储内容划线,代表是常量,从此不能再更改。
const与指针类型。
const int *p = NULL;
int const *p = NULL;//两种写法完全等价
<span style="white-space:pre"> </span>int *const p = NULL;//与上两种有区别
const int *const p = NULL;//两种写法完全等价
int const *const p = NULL;
注意以下写法。
<span style="white-space:pre"> </span>int x = 3;
const *p = &x;
//p = &x;//正确
//*p = 4;//错误,因为定义为const,就不能修改,如果不是const则可以
变量名|
存储地址 |
存储内容
x &x 3
p &p &x
如果打印p和*p的话,就是地址值和3。
如果把const的值,放在*后,p的前面,意思就是p=&x被定义为了const,p中的值是x的地址不能改变。但是可以改变*p,通过改变*p可以改变x。
变量名 | 存储地址 | 存储内容
x &x3
p &p &x
<span style="white-space:pre"> </span>int x = 3;
int *const p = &x;
//p=&y;错误,因为那快内存已被定义为&x,不可更改
如果,前后都用了const。
const int x = 3;
const int *const p = &x;
//p=&y;*p=4;都是错的
变量名 | 存储地址 | 存储内容
x &x 3
p &p &x
const与引用。
定义如下。
<span style="white-space:pre"> </span>int x = 3;
const int &y = x;
//x=10;正确
//y=20;错误
变量名 | 存储地址 | 存储内容
x &x 3
const int x = 3;
int *y = &x;//错误,x不可变,*y是可变的,因此存在风险,通过改变*y改变x,编译器禁止
int x = 3;
const int *y = &x;//指针*y指向的位置不可变,只有读权限,改变x可以改变*p,允许
void fun(const int &a,const int &b)
{
a = 10;//错误,不能给常量赋值
b = 20;
}
sizeof的应用。
//sizeof的应用
char* ss1 = "01234567890"; cout << sizeof(ss1) << endl;//输出的是字符指针,指针固定大小4字节,输出为4
char ss2 = "01234567890"; cout << sizeof(ss2) << endl;//1个char,1个字节,加隐含的"\0",所以是11
char ss3[100] = "01234567890"; cout << sizeof(ss3) << endl;//100
int ss4[100]; cout << sizeof(ss4) << endl;//int为4字节,输出400
char q1[] = "abc"; cout << sizeof(q1) << endl;//4
char q2[] = "a\n"; cout << sizeof(q2) << endl;//"\n"为一个字节,加隐含的"\0",3
char* q3 = "a\n"; cout << sizeof(q3) << endl;//指针,4
char *str1 = (char*)malloc(100); cout << sizeof(str1) << endl;//4
char *str2 = (void*)malloc(100); cout << sizeof(str2) << endl;//4
考虑下面两个结构体的size。
class B
{
private:
bool m_bTemp;
int m_nTemp;
bool m_bTemp2;
};
class C
{
private:
int m_nTemp;
bool m_bTemp;
bool m_bTemp;
};
cout << sizeof(B) << sizeof(C) << endl;
由于在内存中遵循对齐的规则,并且内存寻址以4字节为单位,两个在数据中存放样式如下
B:
|bool|——|——|——|
| int |
|bool|——|——|——|
C:
| int |
|bool|bool|——|——|
所以输出为,12,8。
Q:sizeof和strlen之间的区别
char *ss = "01234567890";
sizeof(ss);//指针的大小,输出为4
sizeof(*ss);//*ss的第一个字符,输出为1
char ss[] = *ss = "01234567890";
sizeof(ss);//加上“\0”,结果为11
sizeof(*ss);//*ss的第一个字符,输出为1
char ss[100] = "0123456789";
sizeof(ss); //结果为100
strlen(ss);//结果为10,计算字符串长度,遇到“\0”停止
int ss[100] = "0123456789";
sizeof(ss);//结果为400
strlen(ss);//结果错误,只能参数为char*,且是以“\0”结尾
class X
{
int i;
int j;
char k;
};
X x;
sizeof(X);//12,内存要对齐
sizeof(x)//12
sizeof是算符,strlen是函数。
Q:内联函数和宏定义的差别是什么?
内联函数和普通函数相比可以加快程序运行的速度,因为不需要中断调用,编译时直接把内联函数的代码镶嵌到目标代码中,提升效率。一般逻辑简单,不用反复调用的函数可以写为inline。