iOS开发之C++相关知识

195 阅读4分钟

用函数调用所给出的实参(实际参数,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可以是名字空间、类、结构;

   :一般用来表示继承;

\

四、指向结构体类型的指针

**
**

以下三种形式等价

  1. 结构体变量 . 成员名
  2. (*p).成员名
  3. 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数组空间 

\

温故知新,请大家多多分享

\

\

\