【整理】指针和引用初探

大部文章分都有提及到以下几点

相同点

  • 都是地址的概念:指针指向一块内存,它的内容是所指内存的地址;而引用则是某块内存的别名。

不同点

  • 指针是一个实体,而引用仅是个别名
  • 引用只能在定义时被初始一次之后不可变;指针可变;引用“从一而终”,指针可以“见异思迁”;
  • 引用没有const,指针有const,const的指针不可变;
  • 引用不能为空,指针可以为空;
  • “sizeof 引用”得到的是所指向的变量(对象)的大小,而“sizeof 指针”得到的是指针本身的大小;typeid(T) == typeid(T&) 恒为真,sizeof(T) == sizeof(T&) 恒为真,但是当引用作为成员时,其占用空间与指针相同(没找到标准的规定)。
  • 指针和引用的自增(++)运算意义不一样;
  • 引用是类型安全的,而指针不是 (引用比指针多了类型检查)

私有析构函数和虚析构函数

私有析构函数

避免在栈上创建对象,在堆上new的空间可以自己控制生命周期。也避免对象被别人通过delete删除。但是需要自己提供destory函数来删除对象。

http://www.aichengxu.com/view/54771

虚析构函数

当基类的指针指向子类的对象时,如果使用delete释放该指针,则只会调用基类的析构函数。所以需要将基类的析构函数定义为虚函数,达到先析构子类,再析构父类的目的。

http://c.biancheng.net/cpp/biancheng/view/247.html

friend关键字

友元函数

友元函数是可以直接访问类的私有成员的非成员函数。它是定义在类外的普通函数,它不属于任何类,但需要在类的定义中加以声明,声明时只需在友元的名称前加上关键字friend。

friend 类型 函数名(形式参数);

  • 友元函数的声明可以放在类的私有部分,也可以放在公有部分,它们是没有区别的,都说明是该类的一个友元函数。
  • 一个函数可以是多个类的友元函数,只需要在各个类中分别声明。
  • 友元函数的调用与一般函数的调用方式和原理一致。

优缺点

  • 可提高性能,如:用友元函数重载操作符和生成迭代器类
  • 破坏了类的封装性和隐藏性,使得非成员函数可以访问类的私有成员。

运算符friend重载和成员重载

  • 成员重载只有一个参数,并且左侧变量必须为类的对象。
    1
    2
    3
    4
    5
    6
    7
    8
    class Complex{
    Complex operator+(int &c2);// 声明重载运算符的函数
    }
    // 定义重载运算符的函数
    Complex Complex::operator+(int &c2){
    }
1
2
3
4
Complex c1;
Complex c2;
c2 = c1 + 2;
//c2 = 2 + c1; // 错误

内存分配与拷贝

realloc

先判断当前的指针是否有足够的连续空间,如果有,扩大mem_address指向的地址,并且将mem_address返回;如果空间不够,先按照newsize指定的大小分配空间,将原有数据从头到尾拷贝到新分配的内存区域,而后释放原来mem_address所指内存区域,同时返回新分配的内存区域的首地址。即重新分配存储器块的地址。

声明

void *realloc(void *ptr, size_t size)

参数

  • ptr — 指针指向一个要重新分配内存的内存块,该内存块之前是通过调用 malloc、calloc或realloc进行分配内存的。如果为空指针,则会分配一个新的内存块(未初始化),且函数返回一个指向它的指针。
  • size — 内存块的新的大小,以字节为单位。如果大小为 0,且ptr 指向一个已存在的内存块,则ptr所指向的内存块会被释放,并返回一个空指针。
  • 返回值
    该函数返回一个指针 ,指向重新分配大小的内存。如果请求失败,则返回 NULL。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#include <stdio.h> /* printf, scanf, puts */
#include <stdlib.h> /* realloc, free, exit, NULL */
int main()
{
char *str;
/* 最初的内存分配 */
str = (char *) malloc(15);
strcpy(str, "jikexueyuan");
printf("String = %s, Address = %un", str, str);
/* 重新分配内存 */
str = (char *) realloc(str, 25);
strcat(str, ".com");
printf("String = %s, Address = %un", str, str);
free(str);
return(0);
}

私有、公有与保护(private/public/protected)

公有成员

可以被对象直接访问,可以被派生类直接访问。

私有成员

只能由类的成员间接访问,不能被派生类访问。

保护成员

只能由类的成员间接访问,可以被派生类直接访问。

公有继承(public)

公有继承的特点是基类的公有成员和保护成员作为派生类的成员时,它们都保持原有的状态,而基类的私有成员仍然是私有的,不能被这个派生类的子类所访问。

(1) 基类成员对其对象的可见性:
公有成员可见,其他不可见。这里保护成员同于私有成员。

(2) 基类成员对派生类的可见性:
公有成员和保护成员可见,而私有成员不可见。这里保护成员同于公有成员。

(3) 基类成员对派生类对象的可见性:
公有成员可见,其他成员不可见。

在公有继承时,派生类的对象可以访问基类中的公有成员;派生类的成员函数可以访问基类中的公有成员和保护成员。