一. 指针
声明: int *a = 3; 声明了一个int类型的指针变量a,初始值为3。
赋值: int b = 3; a = &b; 将变量a的值(即地址)指向b,得到 *a == 3。
指针的好处:
1. 处理堆中存放的大量数据;
2. 快速访问类的成员数据和函数;
3. 以别名方式向函数传递参数。
const与指针:
指向常量的指针是指针的值(地址)可以修改,可以指向其它const对象,但指针所指向的对象不能修改。
如:
const double *a;
const double b = 5.0;
a = &b; //right
*a = 3.14 //error,不能通过指针来修改所指对象。
常指针是指针的值不能修改,但指针所指向的对象却可以修改。
如:
double* const a;
a = &b; //error,指针a是一个常指针
*a = 3; //right
二. 堆和栈
程序在内存中的存放形式有:
1. 栈区。由编译器自动分配并释放,一般存放函数参数,局部变量等。
2. 堆区。由程序员分配并释放,若程序员不释放,程序结束后由操作系统回收。
3. 静态区(全局区)。全局变量和静态变量,程序结束后由系统释放。
4. 文字常量区。常量字符串,程序结束后由系统释放。
5. 程序代码区。函数体的二进制代码。
6. 寄存器区。用来保存栈顶指针和指令指针。
栈中存放的数据时临时的,全局变量可以解决这个问题,但它永远不会被释放,除非程序结束,并且它的值很容易被修改,使用堆就可以解决这两个问题。
堆与栈的区别
1. 内存申请方式不同
栈:自动,如int a; 就在内存中开辟了8个字节的空间。
堆:需要程序员自己申请,因此也需指明变量的大小。
2. 系统响应不同
栈:只要栈的剩余空间大于申请空间,就提供内存,否则提示overflow,也就是栈溢出。
堆:系统首先遍历空闲地址链表,找到符合要求的就删除该空闲地址链表,然后在这块区域的首地址处记录大小(效率低,容易产生碎片)。
3. 空间大小不同
栈:连续内存区域,2M,小量数据。
堆:不连续,通过链表串联,大量数据。
总结
栈与堆结合,在存储大型数据,将数据放在堆中,将指向该数据的指针放到栈中。
三. 用指针创建堆中的对象
堆中的每个内存单元都是匿名的,因此必须先在堆中申请一个内存单元地址,然后把它保存到一个指针中,这样只有使用指针才能访问该内存单元的数据。
用new创建一个对象并分配内存
int *p = new int;
delete p; //释放p所指向的内存空间
p = 0; //使用delete后最好将指针清零
用malloc
int *p = (int *)malloc(sizeof(int));
free(p);
关于new/delete与malloc/free
1. new/delete是运算符,malloc/free是函数。
2. new除了分配内存,还调用了构造函数,同理delete也会调用析构函数;而malloc/free只会分配内存,不会执行构造函数和析构函数。
3. 内存泄露对于malloc和new都可以检查出来,区别是new可以指明是哪个文件的哪一行,malloc没有这些信息。
内存泄露
指针消失,计算机再也找不到该内存区域,好像丢失了这块内存一样。
例:
int *p= new int;
p = new int;
先前申请的8个字节空间就丢失,再也找不到了。
四. 引用
引用就是别名常量,它只能被初始化(不能赋值),跟古代的女人一样,一旦嫁给某人就永远属于他。
int a = 3;
int &ra = a; //&在这里是引用运算符,ra是a的引用,也就是a的别名,地址与a相同。
引用在函数传参上很方便有效。
五. 函数传参
一般分为值传递和地址传递(或者别名)两种:
#include <iostream>
#include <stdio.h>
using namespace std;
/*
按值传递需要建立参数的副本,当传递较大的对象时,需要用引用或者指针。
在按值传递的过程中,不仅需要复制对象,还要调用默认复制构造函数,该函数的作用就是创建某个对象的临时副本;
返回时,副本会被删除,因此也会调用析构函数。
参数传递中:int* const a(指针的值不能边,指针所指向的对象的值可以变) 等同于 int& a(别名常量,a不能指向其他对象,但值可以改变)
const int* const a 等同于 const int& a
*/
class A
{
public:
A(){printf("构造函数执行\n");}
A(A&) {printf("复制构造函数执行\n");}
~A() {printf("析构函数执行\n");}
};
A fuc(A one)
{
return one;
}
void SwapByValue(int a, int b)
{
int t;
t = a;
a = b;
b = t;
}
void SwapByPoint(int* a, int* b)
{
int t;
t = *a;
*a = *b;
*b = t;
}
void SwapByRef(int &a, int &b)
{
int t;
t = a;
a = b;
b = t;
}
int main()
{
int a=3,b=4;
SwapByValue(a,b);
printf("%d %d\n",a,b);
SwapByPoint(&a,&b);
printf("%d %d\n",a,b);
SwapByRef(a,b);
printf("%d %d\n",a,b);
A a1;
A b1;
b1 = fuc(a1);
return 0;
}
分享到:
相关推荐
c++智能指针介绍 由于 C++ 语言没有自动内存回收机制,程序员每次 new 出来的内存都要... RAII 的主要原则是为所有堆分配资源提供所有权,例如动态分配内存或系统对象句柄、析构函数包含要删除或释放资源的代码的堆栈分
堆栈数据结构的c++实现,购物的实例实现。 堆栈的数据结构包括:所需变量和指针 堆栈的操作:空、满、入、出
学习C++新手通常会对指针的使用比较头疼,其实指针的概念很简单,只要能悟清楚这样一个简单的道理就能对指针有一定的认识了: 例如 int *a = new int[10]; 一维指针其实就相当于一维数组,不用去看书上所说的数组在...
也许你从书上了解到了C++的函数参数和返回值类型有类对象,引用,指针。 但是却不知道在内存中到底是怎么回事。本文档从内存堆栈分别揭示了这6种情况下到底在这个过程中发生了什么事情。
9.9.7 引用类的析构函数和结束函数 9.9.8 通用类 9.10 小结 9.11 练习 第10章 调试技术 10.1 理解调试 10.1.1 程序故障 10.1.2 常见故障 10.2 基本的调试操作 10.2.1 设置断点 10.2.2 设置跟踪点 10.2.3 启动调试...
9.9.7 引用类的析构函数和结束函数 9.9.8 通用类 9.10 小结 9.11 练习 第10章 调试技术 10.1 理解调试 10.1.1 程序故障 10.1.2 常见故障 10.2 基本的调试操作 10.2.1 设置断点 10.2.2 设置跟踪点 10.2.3 启动调试...
9.9.7 引用类的析构函数和结束函数 9.9.8 通用类 9.10 小结 9.11 练习 第10章 调试技术 10.1 理解调试 10.1.1 程序故障 10.1.2 常见故障 10.2 基本的调试操作 10.2.1 设置断点 10.2.2 设置跟踪点 10.2.3 启动调试...
9.9.7 引用类的析构函数和结束函数 9.9.8 通用类 9.10 小结 9.11 练习 第10章 调试技术 10.1 理解调试 10.1.1 程序故障 10.1.2 常见故障 10.2 基本的调试操作 10.2.1 设置断点 10.2.2 设置跟踪点 10.2.3 启动调试...
9.9.7 引用类的析构函数和结束函数 9.9.8 通用类 9.10 小结 9.11 练习 第10章 调试技术 10.1 理解调试 10.1.1 程序故障 10.1.2 常见故障 10.2 基本的调试操作 10.2.1 设置断点 10.2.2 设置跟踪点 10.2.3 启动调试...
9.9.7 引用类的析构函数和结束函数 9.9.8 通用类 9.10 小结 9.11 练习 第10章 调试技术 10.1 理解调试 10.1.1 程序故障 10.1.2 常见故障 10.2 基本的调试操作 10.2.1 设置断点 10.2.2 设置跟踪点 10.2.3 启动调试...
压缩包里面包含多个目录,包含了多种查找算法、递归的示例、堆栈使用、队列、二叉树、各种排序算法、进制转换与位操作、链表的使用、C++模板类与模板函数、数组的使用、流与文件、素数与回文数、图论、指针的使用。...
调用函数时,计算机常用栈来存储传递给函数的参数。 栈是一种先进后出的数据结构,栈有一个...函数计算结束以后,或者调用者、或者函数本身修改堆栈,使堆栈恢复原装。 在参数传递中,有两个重要的问题必须要明确说明
5.4 按引用调用函数 5.5 指针与常量限定符 5.6 按引用调用的冒泡排序 5.7 指针表达式与指针算法 5.8 指针与数组的关系 5.9 指针数组 5.10 实例研究:洗牌与发牌 5.11 函数指针 5.12 字符与字符串处理简介 ...
总结的c++面试试题,非常全面,并且大部分都有解答,希望对找工作的朋友有用,或者小型企业人事主管等非计算机专业面试出题有用 英华达: 1.限制变量的作用域 2.设置变量的存储域 7. 引用与指针有什么区别? 1) ...
9.9.7 引用类的析构函数和结束函数 514 9.9.8 通用类 516 9.10 小结 527 9.11 练习 528 第10章 调试技术 531 10.1 理解调试 531 10.1.1 程序故障 532 10.1.2 常见故障 533 10.2 基本的调试操作 534...
5.4 按引用调用函数 5.5 指针与常量限定符 5.6 按引用调用的冒泡排序 5.7 指针表达式与指针算法 5.8 指针与数组的关系 5.9 指针数组 5.10 实例研究:洗牌与发牌 5.11 函数指针 5.12 字符与字符串处理简介 ...
c++中的源程序: 代码如下:class X {private: int i;}; int main() { X x;}上面的类X没有定义构造函数,仅仅有一个int i。 下面为其汇编程序: 代码如下:; 7 : int main() { push ebp;ebp为一个寄存器,总是...
本书以流行的面试题讲解为主要内容,介绍了C、C++语言基本概念,包括保留字、字符串、指针和引用、结构体、库函数等各个方面的基础知识,介绍了面向对象编程基本概念,包括如何实现继承、多态和封装等。还介绍了排序...
本文将简单介绍Linux中C/C++程序运行时堆栈获取,首先来看backtrace系列函数——使用范围适合于没有安装GDB或者想要快速理清楚函数调用顺序的情况 ,头文件execinfo.h int backtrace (void **buffer, int size); 该...
这样声明之后,相当于告诉C, 函数const void f(void)是在C++语言的文件中声明或者实现的,c程序可以使用这个C++中的函数了,从而实现C++和c的混合编程。 13、编写一个函数,作用是把一个char组成的字符串...