案例分析
假設程序要存入1000首歌的歌名束铭,其中最長的歌名可能要30個字節(jié),短的歌名可能就2個字節(jié),大部分歌名是10個字節(jié)左右锈颗。
如果用普通的char數組"char musics[1000][30]"來存儲這些歌名诵闭,需要1000*30=30000個字節(jié)炼团。而實際平均下來,可能有效的字節(jié)也就1000*10=10000個疏尿,浪費了20000字節(jié)瘟芝。
如果換成動態(tài)數組來存儲這1000個歌名,那么將節(jié)省很多內存褥琐。
- 算法思路
用一個指針數組char* musics[1000]锌俱,(占用1000*4=4000字節(jié)的內存)存放1000個指向char的指針,每個指針指向的地址都存放著一個歌名敌呈, 這個內存是動態(tài)創(chuàng)建的贸宏。所以總共需要4000+10000=14000個字節(jié)的內存。最終節(jié)省了30000-14000=16000字節(jié)的內存磕洪。如果這個數組更加大型吭练,那么將節(jié)省更多內存。
示例代碼C++
#include<iostream>
#include<cstring>
#define NUM 5 //總音樂數
using namespace std;
char *getname(); //聲明函數原型
int main()
{
int sum = 0; //保存音樂名字占的總內存字節(jié)數
char* music[NUM]; //創(chuàng)建NUM個指向char的指針析显,組成一個指針數組
for (int i = 0; i < NUM; i++)
{
music[i] = getname(); //將新加入的字符串的地址存入指針數組,指針就有明確的指向了
}
printf("\n成功存入%d個音樂鲫咽!\n",NUM);
printf("音樂指針數組(%d個指針)總共占用內存%d字節(jié)。\n", NUM, sizeof(music));
printf("音樂指針數組第一個元素(還是指針)占用內存%d字節(jié)谷异。\n", sizeof(music[0])); //等價于*music
printf("第三首音樂名字占用內存%d字節(jié)浑侥。\n", strlen(music[2])); //等價于*(music+2)
for (int i = 0; i < NUM; i++)
{
printf("音樂 %d :%s\n",i,music[i]);
sum += strlen(music[i]);
delete music[i]; //用完釋放這個指針,一定記得晰绎,否則內存泄漏
}
printf("音樂名字總共占用%d字節(jié)內存寓落。\n",sum);
printf("已釋放所有內存!\n");
return 0;
}
char * getname()
{
char temp[30]; //創(chuàng)建一個臨時的字符數組變量荞下。30字節(jié)對應于最大可能的音樂名字
cout << "請輸入要添加的音樂名字:";
cin >> temp;
char *p_name = new char[strlen(temp)+1]; //動態(tài)開辟一個內存空間伶选,夠存放新輸入的字符串就行
strcpy(p_name, temp); //復制temp字符串的值到p_name指向的內存中
return p_name; //返回的是一個指針(一個地址)
}
代碼分析
- 如果修改getname()函數史飞,不是從鍵盤手動輸入1000個音樂名,而是從某個文件讀取仰税,更有實用性构资。
- 代碼里演示了指針使用的幾個注意點:
1、指針只能保存地址陨簇,先給指針指定具體的地址吐绵,再去賦值。
2河绽、字符串變量和常量都只表示為一個首地址己单。
3、動態(tài)內存開辟了一定要一一對應釋放耙饰∥屏可以跨函數使用
4、C++里面的new和delete關鍵字對應C里面的malloc()和free()函數苟跪。
5廷痘、C++和C很像,很多可以通用件已。如ptintf函數笋额。C++使用C的頭文件,就把頭文件名前加c篷扩,并去掉.h 鳞陨,如cstring對應string.h
示例代碼C
#include<stdio.h>
#include<stdlib.h> //malloc()和free()函數聲明
#include<string.h>
#define NUM 5 //總音樂數
char *getname(); //聲明函數原型
int main()
{
int sum = 0; //保存音樂名字占的總內存字節(jié)數
char* music[NUM]; //創(chuàng)建NUM個指向char的指針,組成一個指針數組
for (int i = 0; i < NUM; i++)
{
music[i] = getname(); //將新加入的字符串的地址存入指針數組,指針就有明確的指向了
}
printf("\n成功存入%d個音樂瞻惋!\n", NUM);
printf("音樂指針數組(%d個指針)總共占用內存%d字節(jié)。\n", NUM, sizeof(music));
printf("音樂指針數組第一個元素(還是指針)占用內存%d字節(jié)援岩。\n", sizeof(music[0])); //等價于*music
printf("第三首音樂名字占用內存%d字節(jié)歼狼。\n", strlen(music[2])); //等價于*(music+2)
for (int i = 0; i < NUM; i++)
{
printf("音樂 %d :%s\n", i, music[i]);
sum += strlen(music[i]);
free(music[i]); //用完釋放這個指針,一定記得享怀,否則內存泄漏
}
printf("音樂名字總共占用%d字節(jié)內存羽峰。\n", sum);
printf("已釋放所有內存!\n");
return 0;
}
char * getname()
{
char temp[30]; //創(chuàng)建一個臨時的字符數組變量添瓷。30字節(jié)對應于最大可能的音樂名字
printf("請輸入要添加的音樂名字:");
gets(temp);
char *p_name = (char*)malloc(strlen(temp) + 1); //動態(tài)開辟一個內存空間梅屉,夠存放新輸入的字符串就行
strcpy(p_name, temp); //復制temp字符串的值到p_name指向的內存中
return p_name; //返回的是一個指針(一個地址)
}
使用vs編譯代碼,可能的報錯
error C4996: 'strcpy': This function or variable may be unsafe. Consider using strcpy_s instead.
To disable deprecation, use _CRT_SECURE_NO_WARNINGS.
- 并不是代碼有問題鳞贷,而是vs編譯器有問題坯汤。
- 解決方法
更改預處理定義:
項目->屬性->配置屬性->C/C++ -> 預處理器 -> 預處理器定義,增加:
_CRT_SECURE_NO_DEPRECATE