时间:2018/11/23
地点:元征总部
天气:晴
笔记
1.定义
(1)地址或反引用操作符Operator of address or dereference (&)
它被用作一个变量前缀,可以被翻译为“…的地址”("address of"),因此:&variable1 可以被读作 variable1的地址("address of
variable1" )。
(2)
引用操作符Operator of reference (*)
它表示要取的是表达式所表示的地址指向的内容。它可以被翻译为“…指向的数值” ("value pointed by")。
* mypointer 可以被读作 "mypointer指向的数值"。
2.指针(1)
int andy, fred, *ted;
andy = 25;
fred = andy;
ted = &andy;
*ted += 1;
cout << "andy:" << andy << endl;
cout << "&andy:" << &andy << endl;
cout << "fred:" << fred << endl;
cout << "&fred:" << &fred << endl;
cout << "ted:" << ted << endl;
cout << "*ted:" << *ted << endl;
输出:
andy:26
&andy:003CFC8C
fred:25
&fred:003CFC80
ted:003CFC8C
*ted:26
3.指针(2)
int arr[5] = {1,3,5,7,9};
cout << "arr:" << arr << endl;
cout << "arr+1:" << arr+1 << endl;
cout << "*arr:" << *arr << endl;
cout << "*arr+1:" << *arr+1 << endl;
cout << "*(arr+1):" << *(arr+1) << endl;
cout << "sizeof(arr)/sizeof(int):" << sizeof(arr)/sizeof(int) << endl;
输出:
arr:002AFB08
arr+1:002AFB0C
*arr:1
*arr+1:2
*(arr+1):3
sizeof(arr)/sizeof(int):5
4.地址可以比较: if(地址1 == 地址2)
5.指针(3)
int *p1;
char *p2;
float *p3;
cout << "sizeof(p1):" << sizeof(p1) << endl;
cout << "sizeof(p2):" << sizeof(p2) << endl;
cout << "sizeof(p3):" << sizeof(p3) << endl;
输出:
sizeof(p1):4
sizeof(p2):4
sizeof(p3):4
6.指针(4)
int numbers[5];
int *p;
p = numbers;
*p = 10;
p++;
*p = 20;
p = &numbers[2];
*p = 30;
p = numbers+3;
*p = 40;
p = numbers;
*(p+4) = 50;
for(int i=0;i<5;i++)
cout << numbers[i] << ',';
输出:
10,20,30,40,50,
7.中括号[]也叫位移操作符,它相当于在指针中的地址上加上括号中的数组。以下两个表达式等价:
a[5] = 0; <==> *(a+5) = 0;
8.递增(++)和递减(--)操作符比引用操作符(*)有更高的优先级:
*p++=*q++; <==> *p=*q;p++;q++;
9.指针(5)
char a;
char *b;
char **c;
a = 'a';
b = &a;
c = &b;
printf("a的值(a):%c\n",a);
printf("a的地址(&a):%p\n\n",&a);
printf("b的值(b):%p\n",b);
printf("b的地址(&b):%p\n",&b);
printf("b的值指向的内容(*b):%c\n\n",*b);
printf("c的值(c):%p\n",c);
printf("c的地址(&c):%p\n",&c);
printf("c的值指向的内容(*c):%p\n",*c);
printf("c的值指向的内容的地址(&(*c)):%p\n",&(*c));
printf("c的地址指向的内容(*(&c)):%p\n",*(&c));
printf("c的值指向的内容指向的内容(**c):%c\n",**c);
printf("c的值指向的内容指向的内容的地址(&(**c)):%p\n",&(**c));
printf("c的地址指向的内容指向的内容(**(&c)):%p\n",**(&c));
printf("c的地址指向的内容的地址(&(*(&c))):%p\n",&(*(&c)));
printf("c的值指向的内容的地址指向的内容(*(&(*c):%p\n",*(&(*c)));
输出:(以下地址为了方便观察)
a的值(a):a
a的地址(&a):0x1111
b的值(b):0x1111
b的地址(&b):0x2222
b指向的内容(*b):a
c的值(c):0x2222;
c的地址(&c):0x3333
c的值指向的内容(*c):0x1111
c的值指向的内容的地址(&(*c)):0x2222
c的地址指向的内容(*(&c)):0x2222
c的值指向的内容指向的内容(**c):a
c的值指向的内容指向的内容的地址(&(**c)):0x1111
c的地址指向的内容指向的内容(**(&c)):0x1111
c的地址指向的内容的地址(&(*(&c))):0x3333
c的值指向的内容的地址指向的内容(*(&(*c))):0x1111
10.空指针(void *)是一种特殊类型的指针,可以指向任一类型的数据。但是被指向的数值不可以被直接引用(不可以对它们使用引用星号*),因为它的长度是不定的,必须使用类型转换操作或赋值操作来把void指针指向一个具体的数据类型。
11.函数指针
int addition(int a, int b){return (a+b);}
int subraction(int a, int b){return (a-b);}
int (*minus)(int,int) = subraction;
int operation(int x,int y,int (*functocall)(int,int)){
int g;
g = (*functocall)(x,y);
return (g);
}
int main(){
int m,n;
m = operation(7,5,addition);
n = operation(20,m,minus);
}
12.动态内存分配
(1)操作符new和new[]
pointer=new type:给一个单元素的数据类型分配内存
pointer=new type [elements]:给一个数组分配内存
(2)删除操作符delete
delete pointer:删除给单个元素分配的内存
delete[] pointer:删除数组的内存分配
13.#include<stdlib.h>库函数申请/释放内存:
(1)申请内存:
void *malloc(size_t nbytes); //int *p=(int *)malloc(5*sizeof(int));
void *calloc(size_t nelements,size_t size); //int *p=(int *)calloc(5,sizeof(int));
void *realloc(void *pointer, size_t size); //int *p=(int *)realloc(p,10); 重新分配内存
(2)释放内存:
void free(void *pointer);
//这个函数只能被用来释放由malloc,calloc,realloc所分配的内存
14.联合(union):union 中的所有被声明的元素占据同一段内存空间,其大小取声明中最长的元素的大小
union mix_t{
long l;
struct {
short hi;
short lo;
} s;
char c[4];
} mix;
//此联合体占用了4字节
15.匿名联合:此处不给赋予union的object名称,称为匿名联合;可以直接使用union中元素的名字来访问该元素;
struct{
char c;
union{
float x; //直接访问obj.x
int y; //直接访问obj.y
};
}obj;
16.类中的范围标志:
(1)private:只有同一个class的其他成员或该class的"friend"class可以访问这些成员
(2)protected:只有同一个class的其他成员,或该class的"friend"class,或该class的子类(derived class)可以访问这些成员
(3)public:任何可以看到这个class的地方都可以访问这些成员
注意:如果我们在定义一个class成员的时候没有声明其允许范围,这些成员将被默认为private范围。17.操作符重载
(1)原型定义:type operator sign (parameters);
(2)可被重载的操作符列表:
+ - * / = < > += -= *= /= << >>
<<= >>= == != <= >= ++ -- % & ^ ! |
~ &= ^= |= && || %= [] () new delete
(3)例子:
Data operator + (Data);
17.总结不同操作符函数如何定义声明(用操作符替换每个@):
Expression | Operator(@) | Function member | Global function |
---|---|---|---|
@a | + - * & ! ~ ++ -- | A::operator@() | operator@(A) |
a@ | ++ -- | A::operator@(int) | operator@(A,int) |
a@b | + - * / % ^ & | < > == != <= >= << >> && || | A::operator@(B) | operator@(A,B) |
a@b | + += -= *= /= %= ^= &= |= <<= >>= [] | A::operator@(B) | - |
a(b,c...) | () | A::operator()(B,C...) | - |
a->b | -> | A::operator->() | - |
18.关键字this:通常被用在一个class内部,指正在被执行的该class的对象(object)在内存中的地址。它是一个指针,其值永远是自身object的地址。
作用:
(1)它可以被用来检测传入一个对象的成员函数的参数是否是该对象本身。例如:
class CDummy{
public:
int isitme(CDummy& param);
};
int CDummy::isitme(CDummy& param){
if(¶m == this)return 1;
else return 0;
}
int main()
{
CDummy a;
CDummy *b = &a;
if(b->isitme(a))
cout << "yes,&a is b";
return 0;
}
(2)被用在成员函数operator=中,用来返回对象的指针(避免使用临时对象)例如:
class CDummy{
public:
int x,y;
CDummy& operator=(const CDummy& param);
};
CDummy& CDummy::operator=(const CDummy& param)
{
x = param.x;
y = param.y;
return *this;
}
int main()
{
CDummy a,c;
a.x = 1;
a.y = 2;
c = a;
cout << c.x << endl;
cout << c.y << endl;
return 0;
}
PS:实际上,如果我们没有定义成员函数operator=,编译器自动为该class生成的默认代码有可能就是这个样子的。
19.静态成员:存放于全局变量区(对同一个class的所有object是同一个值)
class CDummy {
public:
static int n;
CDummy () { n++; };
~CDummy () { n--; };
};
int CDummy::n=0;//必须在全局中初始化静态变量
int main () {
CDummy a;
CDummy b[5];
CDummy * c = new CDummy;
cout << a.n << endl;
delete c;
cout << CDummy::n << endl;
return 0;
}
输出:
7
6