C语言
malloc
void malloc(size_t size);
size_t就是unsign int无符号正整数
#include <stdio.h>
#include <stdlib.h>
int main()
{
int* ptr = NULL;
int num, i;
printf("请输入待录入整数的个数:");
scanf_s("%d", &num);
ptr = (int*)malloc(num * sizeof(int));
for (i = 0; i < num; i++)
{
printf("请录入第%d个整数:", i + 1);
scanf_s("%d", &ptr[i]);
}
printf("The number you scanf is:");
for (i = 0; i < num; i++)
{
printf("%d ", ptr[i]);
}
putchar('\n');
free(ptr);
return 0;
}
#include <stdio.h>
#include <stdlib.h>
int main()
{
int* ptr;
ptr = (int*)malloc(sizeof(int));
if (ptr == NULL)
{
printf("It's wrong!分配内存失败!\n");
exit(1);
}
printf("please input a number:");
scanf_s("%d", ptr);
printf("The number is:%d\n", *ptr);
free(ptr);
//释放掉地址后变为非法空间,所以不会打印出任何东西。
printf("The number is:%d\n", *ptr);
return 0;
}
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
int* ptr1 = NULL;
int* ptr2 = NULL;
//第一次申请的内存空间
ptr1 = (int*)malloc(10 * sizeof(int));
//第一次申请的内存空间不够用
//第二次申请内存空间
ptr2 = (int*)malloc(20 * sizeof(int));
//将ptr1的数据拷贝到ptr2中,memcpy是拷贝,在头文件string.h中
memcpy(ptr2, ptr1, 10);
free(ptr1);
//对ptr2申请的空间做了操作之后
free(ptr2);
return 0;
}
free
void free(void *ptr)
用来释放ptr参数指向的内存空间,必须是由malloc、calloc或relloc函数申请的。
如果ptr参数是NULL,则不执行任何操作
注意:该函数不会修改ptr参数的值,所以调用后它仍指向原来的地方(变为非法空间)
内存泄漏
1、隐式内存泄漏:用完内存块没有及时用free释放
2、丢失内存块地址
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
//没有释放内存空间导致系统崩溃。(内存泄漏)
while(1)
{
malloc(1024);
}
return 0;
}
#include <stdio.h>
#include <stdlib.h>
int main()
{
int* ptr;
int num = 123;
ptr = (int*)malloc(sizeof(int));
if (ptr == NULL)
{
printf("It's wrong!分配内存失败!\n");
exit(1);
}
printf("please input a number:");
scanf_s("%d", ptr);
printf("The number is:%d\n", *ptr);
//这里把num的地址放到了ptr里面导致前面使用malloc申请的内存块丢失
ptr = #
printf("The number is:%d\n", *ptr);
//这里相当于直接对局部变量进行了位释放
free(ptr);
return 0;
}
calloc
void *calloc(size_t, size_t size);
calloc函数在内存中动态地申请nmemb个长度为size的连续内存空间(空间总尺寸为nmemb * size),而且全部初始化为0,相当于malloc加上memset。
而malloc函数不进行初始化操作,里面的数据是随机的
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define N 10
int main()
{
int* ptr = NULL;
int i;
/*
int* ptr = (int*)calloc(8, sizeof(int));
==
int* ptr = (int*)malloc(8 * sizeof(int));
memset(ptr, 0, 8 * sizeof(int));
*/
ptr = (int*)malloc(N * sizeof(int));
if (ptr == NULL)
{
exit(1);
}
//memset 函数使用常量字节c填充s指向的前n个字节,在string头文件里面
//void* memset(void* s, int c, size_t n);
//这里作用貌似就是用0填充一个用malloc创造出空间的ptr数组(数组内一共有十个全是0的元素)
memset(ptr, 0, N * sizeof(int));
for (i = 0; i < N; i++)
{
printf("%d ", ptr[i]);
}
putchar('\n');
// 运行结果是0 0 0 0 0 0 0 0 0 0
free(ptr);
return 0;
}
realloc
void *realloc(void *ptr, size_t size);
realloc函数修改ptr指向的内存空间大小为size字节
如果新分配的内存空间比原来的打,则就内存块的数据不会发生改变;但是如果新的内存空间大小小于旧的内存空间,可能会导致数据丢失,慎用!
该函数将移动内存空间的数据并返回新的指针
#include <stdio.h>
#include <stdlib.h>
int main()
{
int i, num;
int count = 0;
int* ptr = NULL; // 注意这里必须初始化为NULL
do
{
printf("please scanf a int(输入-1表示结束):");
scanf("%d", &num);
count++;
/*
如果ptr参数是NULL,调用该函数相当于调用malloc(size)
如果size参数为0,并且ptr参数不为NULL,那么调用该函数相当于调用free(ptr)
除非ptr参数为NULL,否则ptr的值必须由先前调用malloc、calloc、realloc函数返回
*/
ptr = (int*)realloc(ptr, count * sizeof(int));
if (ptr == NULL)
{
exit(1);
}
ptr[count - 1] = num;
} while (num != -1);
printf("The number you input is :");
for (i = 0; i < count; i++)
{
printf("%d", ptr[i]);
}
putchar('\n');
free(ptr);
return 0;
}
C语言的内存布局
#include <stdio.h>
#include <stdlib.h>
int global_uninit_var;
int global_init_var1 = 520;
int global_init_var2 = 880;
void func(void);
void func(void)
{
;
}
int main()
{
int local_var1;
int local_var2;
static int static_uninit_var;
static int static_init_var = 456;
char* str1 = "I love Fishc.com!";
char* str2 = "You are right!";
int* malloc_var = (int*)malloc(sizeof(int));
printf("addr of func -> %p\n", &func);
printf("addr of str1 -> %p\n", &str1);
printf("addr of str2 -> %p\n", &str2);
printf("addr of global_init_var1 -> %p\n", &global_init_var1);
printf("addr of global_init_var2 -> %p\n", &global_init_var2);
printf("addr of static_init_var -> %p\n", &static_init_var);
printf("addr of static_uninit_var -> %p\n", &static_uninit_var);
printf("addr of global_uninit_var -> %p\n", &global_uninit_var);
printf("addr of malloc_var -> %p\n", &malloc_var);
printf("addr of local_var1 -> %p\n", &local_var1);
printf("addr of local_var2 -> %p\n", &local_var2);
/*
addr of func -> 006313A7
addr of str1 -> 007DFB10
addr of str2 -> 007DFB04
addr of global_init_var1 -> 0063A034
addr of global_init_var2 -> 0063A038
addr of static_init_var -> 0063A03C
addr of static_uninit_var -> 0063A13C
addr of global_uninit_var -> 0063A46C
addr of malloc_var -> 007DFAF8
addr of local_var1 -> 007DFB28
addr of local_var2 -> 007DFB1C
*/
return 0;
}
C++
动态申请内存操作符new
new 类型名T(初始化参数列表)
- 功能:
在程序执行期间,申请用于存放T类型对象的内存空间,并依初值列表赋以初值。 - 结果值:
成功:T类型的指针,指向新分配的内存; 失败:抛出异常。
释放内存操作符delete
delete 指针p
- 功能:释放指针p所指向的内存。
p必须是new操作的返回值
#include <iostream>
using namespace std;
class Point {
public:
Point() :x(0), y(0) {
cout << "Default Constructor called." << endl;
}
Point(int x, int y) :x(x), y(y) {
cout << "Constructor called." << endl;
}
~Point() { cout << "Destructor called." << endl; }
int getX()const { return x; }
int getY()const { return y; }
void move(int newX, int newY) {
x = newX;
y = newY;
}
private:
int x, y;
};
int main()
{
cout << "Step one: " << endl;
Point* ptr1 = new Point; // 调用默认构造函数
delete ptr1; // 删除对象,自动调用析构函数
cout << "Step two: " << endl;
ptr1 = new Point(1, 2);
delete ptr1;
return 0;
}
/*
Step one:
Default Constructor called.
Destructor called.
Step two:
Constructor called.
Destructor called.
*/
分配和释放动态数组
- 分配:new类型名T{数组长度}
数组长度可以是任何整数类型表达式,在运行时计算 - 释放:delete[] 数组名p
释放指针p所指向的数组。
p必须是用new分配得到的数组首地址。
#include <iostream>
using namespace std;
class Point {
public:
Point() :x(0), y(0) {
cout << "Default Constructor called." << endl;
}
Point(int x, int y) :x(x), y(y) {
cout << "Constructor called." << endl;
}
~Point() { cout << "Destructor called." << endl; }
int getX()const { return x; }
int getY()const { return y; }
void move(int newX, int newY) {
x = newX;
y = newY;
}
private:
int x, y;
};
int main()
{
Point* ptr = new Point[2]; // 创建对象数组
ptr[0].move(5, 10); // 通过指针访问数组元素的成员
ptr[1].move(15, 20); // 通过指针访问数组元素的成员
cout << "Deleting..." << endl;
delete[] ptr; // 删除整个对象数组(用两个方括号,用两个能释放两个内存空间,只用一个只释放一个内存空间,导致内存泄漏)
return 0;
}
/*
Default Constructor called.
Default Constructor called.
Deleting...
Destructor called.
Destructor called.
*/
动态创建多维数组
new 类型名T[第1维长度][第2维长度]…;
- 如果内存申请成功,new运算返回一个指向新分配内存首地址的指针。
- 例如:
char(*fp)[3]; fp = new char[2][3];
#include <iostream>
using namespace std;
int main()
{
// cp是指向数组(二维数组)的指针,多维数组去掉第一维的下标个数
int(*cp)[9][8] = new int[7][9][8];
for (int i = 0; i < 7; i++)
for (int j = 0; j < 9; j++)
for (int k = 0; k < 8; k++)
*(*(*(cp + i) + j) + k) = (i * 100 + j * 10 + k);
for (int i = 0; i < 7; i++) {
for (int j = 0; j < 9; j++) {
for (int k = 0; k < 8; k++)
cout << cp[i][j][k] << " ";
cout << endl;
}
cout << endl;
}
delete[]cp;
return 0;
}
#include <iostream>
#include <cassert>
using namespace std;
class Point {
public:
Point() :x(0), y(0) {
cout << "Default Constructor called." << endl;
}
Point(int x, int y) :x(x), y(y) {
cout << "Constructor called." << endl;
}
~Point() { cout << "Destructor called." << endl; }
int getX()const { return x; }
int getY()const { return y; }
void move(int newX, int newY) {
x = newX;
y = newY;
}
private:
int x, y;
};
class ArrayOfPoints { // 动态数组类
public:
ArrayOfPoints(int size) : size(size) {
points = new Point[size];
}
~ArrayOfPoints() {
cout << "Deleteing..." << endl;
delete[] points;
}
Point& element(int index) {
assert(index >= 0 && index < size);
return points[index];
}
private:
Point* points; // 指向动态数组首地址
int size; // 数组大小
};
int main()
{
int count;
cout << "Please enter the count of points: ";
cin >> count;
ArrayOfPoints points(count); // 创建数组对象
points.element(0).move(5, 0); // 访问数组元素的成员
points.element(1).move(15, 20); // 访问数组元素的成员
return 0;
}
/*
Please enter the count of points: 2
Default Constructor called.
Default Constructor called.
Deleteing...
Destructor called.
Destructor called.
*/
#vector
为什么需要vector?
- 封装任何类型的动态数组,自动创建和删除。
- 数组下标越界检查。
vector对象的定义
vector<元素类型> 数组对象名(数组长度);
例:vector<int> arr(5) 建立大小为5的int数组
#include <iostream>
#include <vector>
using namespace std;
double average(const vector <double>& arr)
{
double sum = 0;
for (unsigned i = 0; i < arr.size(); i++)
sum += arr[i];
return sum / arr.size();
}
int main()
{
unsigned n;
cout << "n = ";
cin >> n;
vector<double>arr(n); // 创建数组对象
cout << "Please input " << n << "real numbers: " << endl;
for (unsigned int i = 0; i < n; i++)
cin >> arr[i];
cout << "Average = " << average(arr) << endl;
return 0;
}
#include <iostream>
#include <vector>
using namespace std;
int main()
{
std::vector<int>v = { 1, 2, 3 };
for (auto i = v.begin(); i != v.end; ++i)
std::cout << *i << std::endl;
for (auto e : v)
std::cout << e << std::endl;
return 0;
}
浅层复制
- 实现对象间数据元素的一一对应复制。
不能复制指针(当这个指针指向的空间是用动态内存分配的空间)
深层复制
- 当被复制的对象数据成员是指针类型时,不是复制该指针成员本身,而是将指针所指对象进行复制。(需要开辟新的动态内存空间)
#include <iostream>
#include <cassert>
using namespace std;
class Point {
public:
Point() :x(0), y(0) {
cout << "Default Constructor called." << endl;
}
Point(int x, int y) :x(x), y(y) {
cout << "Constructor called." << endl;
}
~Point() { cout << "Destructor called." << endl; }
int getX()const { return x; }
int getY()const { return y; }
void move(int newX, int newY) {
x = newX;
y = newY;
}
private:
int x, y;
};
class ArrayOfPoints { // 动态数组类
public:
// 在这里创建一个复制构造函数,不适用默认的构造函数
ArrayOfPoints(const ArrayOfPoints& pointsArray);
ArrayOfPoints(int size) : size(size) {
points = new Point[size];
}
~ArrayOfPoints() {
cout << "Deleteing..." << endl;
delete[] points;
}
Point& element(int index) {
assert(index >= 0 && index < size);
return points[index];
}
private:
Point* points; // 指向动态数组首地址
int size; // 数组大小
};
ArrayOfPoints::ArrayOfPoints(const ArrayOfPoints& v)
{
size = v.size; // size的值可以直接复过来
points = new Point[size]; // 指针的不能直接,要开辟新的空间
for (int i = 0; i < size; i++)
points[i] = v.points[i];
}
int main()
{
int count;
cout << "Please enter the count of points: ";
cin >> count;
ArrayOfPoints pointsArray1(count); // 创建对象数组
pointsArray1.element(0).move(5, 10);
pointsArray1.element(1).move(15, 20);
ArrayOfPoints pointsArray2(pointsArray1); // 创建副本,使用的是默认的复制构造函数,只能复制地址,所以在析构的时候使用了两次delete导致出错
cout << "Copy of pointArray1:" << endl;
cout << "Point_0 of array2: " << pointsArray2.element(0).getX() << ", "
<< pointsArray2.element(0).getY() << endl;
cout << "Point_1 of array2: " << pointsArray2.element(1).getX() << ", "
<< pointsArray2.element(1).getY() << endl;
pointsArray1.element(0).move(25, 30);
pointsArray2.element(1).move(35, 40);
cout << "After the moving of pointsArray1:" << endl;
cout << "Point_0 of array2: " << pointsArray2.element(0).getX() << ", "
<< pointsArray2.element(0).getY() << endl;
cout << "Point_1 of array2: " << pointsArray2.element(1).getX() << ", "
<< pointsArray2.element(1).getY() << endl;
return 0;
}
/*
Please enter the count of points: 2
Default Constructor called.
Default Constructor called.
Default Constructor called.
Default Constructor called.
Copy of pointArray1:
Point_0 of array2: 5, 10
Point_1 of array2: 15, 20
After the moving of pointsArray1:
Point_0 of array2: 5, 10
Point_1 of array2: 35, 40
Deleteing...
Destructor called.
Destructor called.
Deleteing...
Destructor called.
Destructor called.
*/