用函数调用所给出的实参(实际参数,actual arguments)向函数定义给出的形参(形式参数,formal arguments)
设置初始值的过程,叫做参数传递(Argument Passing)
在C++中调用函数时有三种参数传递方式:
1、传值调用;
2、传址调用(传指针);
3、引用传递;\
\
我们主要温习一下,C++指针,和引用传参
\
一、指针传参
1、 //函数的声明
void swap(int *, int *);
\
2. //函数的定义
void swap(int *x, int *y){
int temp;
temp = *x;
*x = *y;
*y = temp;
}
\
3.//函数的调用
int i = 8, j = 9;
swap(&i, &j);
总结:指针传参数需要通过 & 拿变量的地址传参,会改变变量的值
\
二、引用传参数
1、//函数的声明
void swap(int &, int &);
\
2、//函数的定义
void swap(int &x, int &y){
int temp;
temp = x;
x = y;
y = temp;
}
\
3、//函数的调用
int i = 8, j = 9;
swap(i, j);
\
总结:引用传参数,直接拿变量传参数,会改变变量的值。
按引用传递,引用实参的引用参数传递给函数,而不是进行参数拷贝。
引用类型的形参与相应的实参占用相同的内存空间,改变引用类型形参的值,相应实参的值也会随着变化
**
**
三、C++ 中.和::和:和->的区别
\
在学习C++的过程中我们经常会用到.和::和:和->,在此整理一下这些常用符号的区别。
A.B则A为对象或者结构体;
A->B则A为指针,->是成员提取,A->B是提取A中的成员B,A只能是指向类、结构、联合的指针;
::是作用域运算符,A::B表示作用域A中的名称B,A可以是名字空间、类、结构;
:一般用来表示继承;
\
四、指向结构体类型的指针
**
**
以下三种形式等价
- 结构体变量 . 成员名
- (*p).成员名
- p->成员名
\
例子:
struct Stusent {
int num;
char name[20];
char sex;
int age;
float score;
char addr[30];
};
\
void passparameter(struct Stusent *stu) {
Stusent *p;
Stusent a;
a = *stu;
p = stu;
strcpy(a.addr, "VIP");
printf("%s",p->addr);
printf("%s",(*p).addr);
printf("%s",a.addr);
}
\
五、C++的智能指针和解决C++中的循环引用
C++11中引入了三种智能指针,分别是shared_ptr、weak_ptr和unique_ptr\
智能指针的作用:智能指针可以帮助我们管理动态分配的堆内存,减少内存泄漏的可能性
循环引用问题:虽然智能指针会减少内存泄漏的可能性,但是如果使用智能指针的方式不对,一样会造成内存泄漏
如下代码会造成循环引用
\
class Bclass; // 前置声明
class Aclass {
public:
shared_ptr ptr;
};
\
class Bclass {
public:
shared_ptr ptr;
};
\
int main() {
shared_ptr pa(new Aclass());
shared_ptr pb(new Bclass());
pa->ptr = pb;
pb->ptr = pa;
}
\
解决方法用 weak_ptr如下:
\
class Bclass;
class Aclass {
public:
weak_ptr weak_p;
};
\
class Bclass {
public:
weak_ptr weak_p;
};
\
int main() {
shared_ptr aa(new Aclass());
shared_ptr bb(new Bclass());
aa->weak_p = bb;
bb->weak_p = aa;
}
原因是:weak_ptr不会增加shared_ptr的计数器,从而离开mian函数作用域时,shared_ptr aa & bb 计数器都 -1 ,成为0, 具备销毁条件,调用析构函数销毁自己和所指对象
\
六、memset 函数的用法
memset 函数是内存赋值函数,用来给某一块内存空间进行赋值的,常用于内存空间初始化
;
原型为 :void *memset(void *s, int v, size_t n);
这里s可以是数组名,也可以是指向某一内在空间的指针;
v为要填充的值;
n为要填充的字节数;
\
例子:
struct Student {
char num[100];
char name[100];
};
\
int main(){
Student stu;
Student stu1[100];
memset(&stu, 0, sizeof(stu)); //注意第一个参数是指针类型,stu不是指针变量,要加&
memset(stu1, 0, sizeof(stu1)); //stu1是数组名,就是指针类型,不需要加&
}
七、malloc函数的用法
原型:void *malloc(long NumBytes):
作用:该函数分配了NumBytes个字节,并返回了指向这块内存的指针(void* 表示未定义指针类型)。如果分配失败,则返回一个空指针(NULL)。
malloc()和free()配合使用,free()函数释放了malloc()函数分配的内存
例子:
\
int main(){
char *Ptr = NULL;
Ptr = (char *)malloc(100 * sizeof(char));
if (NULL == Ptr)
{
exit (1);
}
gets(Ptr);
// code...
free(Ptr);
Ptr = NULL;
}
\
malloc与new的不同点
从函数声明上可以看出。malloc 和 new 至少有两个不同: new 返回指定类型的指针,并且可以自动计算所需要大小
int* parr;
parr = new int [100]; //返回类型为 int* 类型(整数型指针),分配大小为 sizeof(int) * 100;
//而 malloc 则必须由我们计算要字节数,并且在返回后强行转换为实际类型的指针。
int* p;
p = (int *) malloc (sizeof(int));
\
delete用法:
\
1. int *a = new int;
delete a; //释放单个int的空间
\
2.int *a = new int[5];
delete[] a; //释放int数组空间
\
温故知新,请大家多多分享
\
\
\