您的位置:首页 > 编程语言 > C语言/C++

C/C++ Notes: #define和#typedef的区别以及构造函数和析构函数

2016-10-11 07:20 246 查看
#define和#typedef的区别

两者的最主要区别是前者是预编译阶段(没到编译阶段)进行的内容替换。而#typedef是在编译阶段为现有的类型(自定义或者基本类型)创建一个别名。前者在预编译阶段展开时,不会被检查语法,而后者会接受编译阶段的语法检查。

举一个最经典的例子来说明这种字符串替换和定义一个新类型(类型别名)的区别:

#define int_ptr int *
int_ptr a, b; //相当于int * a, b; 只是简单的宏替换

typedef int* int_ptr;
int_ptr a, b; //a, b 都为指向int的指针,typedef为int* 引入了一个新的助记符


Reference: http://zhidao.baidu.com/question/24658120.html

构造函数和析构函数:

析构函数在C++中会给每个类型都自动生成其默认版本的构造函数,这点和Java一样。同样,默认版本的只会为一个对象在堆上分配动态内存,而不会为这片内存初始化。初始化工作需要程序员自定义自己的构造函数。注意,和Java不同的是,C++甚至不会帮你初始化默认值,像指针为NULL或者int为0,C++不会帮你这么做。你不初始化的话,这片内存虽然已经分给你了,但是你还是没办法access。

这里介绍一个C++特有的初始化成员的语法:

Point(int x = 0, int y = 0):xPos(x), yPos(y)  //使用初始化表
{
cout<<"调用初始化表对数据成员进行初始化!\n";
}


Reference: http://www.cnblogs.com/mr-wid/archive/2013/02/19/2917911.html

在 Point 构造函数头的后面, 通过单个冒号 : 引出的就是初始化表, 初始化的内容为 Point 类中int型的 xPos 成员和 yPos成员, 其效果和 xPos = x; yPos = y; 是相同的。

相反地,析构函数是用来释放掉该对象在堆上动态分配的空间的。但它能做的东西很有限:1、它只能释放调用它的对象的动态内存(没错,不同于构造函数,析构函数可以被显示调用,同时也不能被重载)。2、它只能释放堆内存中的基本数据(静态)类型的成员,对于指针(动态)类型的成员,其只能删除堆内存中的指针值(地址值),而指针指向的内容,就无能为力了。所以,这时候需要delete()的出场。

Quoted: 

1、成员变量如果是指针。那么程序需要分配的内存是存储指针占用的内存(32位程序是4个字节)和指针指向的内存。其中指针占用的内存是有编译器管理的,而指针指向的内存是你自己管理的。

也就是,这个指针占用的内存(4个字节)就会自动在析构函数里自动释放。但是指针指向的部分内存默认析构函数是不会帮你释放的,因为编译器也不知道你这个指针指向的是不是你自己分配的内存,也不知道你将来还会不会用这段内存。

2、当程序/进程执行完,程序占用的所有内存都会被操作系统释放。即使没有显示的delete。

Reference: https://segmentfault.com/q/1010000004641190

当用户没有显式定义析构函数时, 编译器同样会为对象生成一个默认的析构函数, 但默认生成的析构函数只能释放类的普通数据成员所占用的空间, 无法释放通过 new 或 malloc 进行申请的空间, 因此有时我们需要自己显式的定义析构函数对这些申请的空间进行释放, 避免造成内存泄露。

#include <iostream>
2      #include <cstring>
3
4      using namespace std;
5
6      class Book
7      {
8          public:
9              Book( const char *name )      //构造函数
10              {
11                  bookName = new char[strlen(name)+1];
12                  strcpy(bookName, name);
13              }
14              ~Book()                 //析构函数
15              {
16                  cout<<"析构函数被调用...\n";
17                  delete []bookName;  //释放通过new申请的空间
18              }
19              void showName() { cout<<"Book name: "<< bookName <<endl; }
20
21          private:
22              char *bookName;
23      };
24
25      int main()
26      {
27          Book CPP("C++ Primer");
28          CPP.showName();
29
30          return 0;
31
32      }


 如果需要显式调用析构函数来释放对象中动态申请的空间只需要使用 对象名.析构函数名(); 即可, 例如上例中要显式调用析构函数来释放 bookName 所指向的空间只要:

CPP.~Book();
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
相关文章推荐