在C++中,sizeof是一个运算符,用于获取特定类型或对象在内存中所占用的字节数。这个运算符在多种场景下都非常有用,包括内存管理、性能优化以及理解数据结构在内存中的布局。数组是一种可以存储多个同类型元素的线性数据结构。每个元素在数组中有一个唯一的索引,通常从0开始。数组提供了一种方便的方式来存储和处理一组相关的数据。
在C++中,获取数组长度并不像获取其他数据类型的大小那样直接,因为数组本身并不包含其长度的信息。所以这篇讲解的是,如何结合sizeof获取数组的长度。并且通过对象指针,也可以获取数组长度。
一、变量类型
在讲sizeof获取数组长度之前,我们先来了解下C++中变量所占用字节空间,这对后面了解sizeof获取数组长度很有帮助。
关键字 | 数的范围 | 字节数 | 描述 |
---|---|---|---|
short | -32768~32767 | 2 | 整型 |
unsigned short | 0~65535 | 2 | 无符号整型 |
int | -2147483648~2147483647 | 4 | 短整型 |
unsigned int | 0~4294967295 | 4 | 无符号短整型 |
long int | -2147483648~2147483647 | 4 | 长整型 |
unsigned long | 0~4294967295 | 4 | 无符号长整型 |
关键字 | 数的范围 | 字节数 | 描述 |
---|---|---|---|
float | -3.4e38~3.4e38 | 4 | 单精度 |
double | -1.7e308~1.7e308 | 8 | 双精度 |
long double | -1.1e4932~1.1e4932 | 10 | 长双精度 |
二、获取数据类型大小
这里我们通过实例代码来演示一下,是否不同数值或大小不一的数值,其类型字节是一样的,代码如下:
#include <iostream>
using namespace std;
int main(){
// 短整形
short gender = 1, gender2 = 2;
cout <<"short byte: " <<sizeof(gender) <<", " <<sizeof(gender2) <<endl;
// 整型
int age = 30, age2 = 50, age3 = 8;
cout <<"int byte: " <<sizeof(age) <<", " <<sizeof(age2) <<", " <<sizeof(age3) <<endl;
// 单精度
float num = 3.14f, num2 = 86.23f;
cout <<"float byte: " <<sizeof(num) <<", " <<sizeof(num2) <<endl;
// 长双精度
long int number = 12341238;
cout <<"long byte: " <<sizeof(number) <<endl;
return 0;
}
从结果上可以看出,可以通过sizeof运算符可以获取数据类型在内存中大小,并且同数据类型的字节空间大小是一样的。如下图:
三、获取对象在内存大小
对于数组或对象实例,sizeof可以返回整个数组或对象所占用的内存大小,而不仅仅是数组中一个元素或对象一个成员的大小。代码如下:
#include <iostream>
using namespace std;
int main(){
int nums[5] = {20, 30, 15, 100, 5000};
cout <<"nums byte: " <<sizeof(nums) <<endl;
double nums2[5] = {20.5, 30.1, 15.8, 100.53, 5000.05};
cout <<"nums2 byte: " <<sizeof(nums2) <<endl;
return 0;
}
从结果可以看出,sizeof运算符输出数组对象的字节空间分别是20和40,int型字节是4,double型字节是8,所以20/4=5,40/8=5。想必大家已经知道如何通过sizeof运算符来计算出数组的长度了。如下图:
四、自定义排序函数
现在我们可以结合sizeof运算符和数组的一个元素大小,计算出数组的长度。而这里将通过自定义数组排序sortArray()函数方式,来实现int数组排序功能。代码如下:
#include <iostream>
using namespace std;
// 定义数组排序函数
void sortArray(int arr[], size_t len){
for(size_t i = 0; i < len - 1; i++){
for(size_t j = i + 1; j < len; j++){
if(arr[i] > arr[j]){
int temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
}
}
};
int main(){
int nums[] = {20, 30, 15, 100, 5000};
size_t numsLen = sizeof(nums) / sizeof(nums[0]); // 计算数组长度
// 对数组内元素进行排序
sortArray(nums, numsLen);
// 打印排序后的数组
for(size_t i = 0; i < numsLen; ++i) {
cout << nums[i] << " ";
}
cout << endl;
return 0;
}
运行结果如下:
注意:sizeof运算符返回的类型是size_t,这是一个无符号整数类型,用于表示对象的大小。
五、函数模板
通过自定义sortArray()函数实现了int类型数组元素从小到大排序,但其他类型(如float、double)也希望通过sortArray()排序,那就需要使用函数重载方法来实现,定义多个sortArray()函数且形参数据类型不同。这样会比较麻烦,可以通过函数模板来解决这问题,简单操作。代码如下:
#include <iostream>
#include <string>
using namespace std;
// 定义数组排序函数模板
template <typename T>
void sortArray(T arr[], size_t len){
for(size_t i = 0; i < len - 1; i++){
for(size_t j = i + 1; j < len; j++){
if(arr[i]>arr[j]){
T temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
}
}
};
// 定义打印数组函数模板
template <typename P>
void printArray(P arr[], size_t len, string title){
cout <<title <<": ";
// 打印排序后的数组
for(size_t i = 0; i < len; ++i) {
cout << arr[i] << " ";
}
cout << endl;
};
int main(){
int nums[] = {65, 30, 15, 100, 5000};
size_t numsLen = sizeof(nums) / sizeof(nums[0]); // 计算数组长度
printArray(nums, numsLen, "print int before"); //打印排序前int数组结果
sortArray(nums, numsLen); //排序int数组
printArray(nums, numsLen, "print int after"); //打印排序后int数组结果
float nums2[] = {3.14f, 8.05f, 1.2f, 0.88f, 9.5f};
size_t nums2Len = sizeof(nums2) / sizeof(nums2[0]); // 计算数组长度
printArray(nums2, nums2Len, "print float before"); //打印排序前float数组结果
sortArray(nums2, nums2Len); //排序float数组
printArray(nums2, nums2Len, "print float after"); //打印排序后float数组结果
long nums3[] = {531138, 782323, 173884, 8813, 64388, 1953};
size_t nums3Len = sizeof(nums3) / sizeof(nums3[0]); // 计算数组长度
printArray(nums3, nums3Len, "print long before"); //打印排序前long数组结果
sortArray(nums3, nums3Len); //排序long数组
printArray(nums3, nums3Len, "print long after"); //打印排序后long数组结果
return 0;
}
通过函数模板定义,可以传入不同数据类型的数组进行排序处理,传入输出结果如下:
六、对象数组指针
在C++中,引用通常用来指向一个已存在的对象,并且一旦初始化就不能再指向其他对象。对于数组来说,可以有一个指向数组的指针,或者一个指向数组首元素的引用。代码如下:
int arr[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
int (*ref)[10] = &arr; //正确写法
int (&ref)[10] = arr; //或者这种也是正确写法
此时,有些人可能在想是否可以在获取数组长度这里再简化点,在调用sortArray()函数时不用传入数组长度,也不用sizeof来计算数组长度呢?当然是可以的,这里可以用对象指针方式,也获取数组长度。现在将函数模板进行简单修改后,再次运行看看效果。代码如下:
#include <iostream>
#include <string>
using namespace std;
// 定义数组排序函数模板
template <typename T, size_t L>
void sortArray(T (&arr)[L]){
for(size_t i = 0; i < L - 1; i++){
for(size_t j = i + 1; j < L; j++){
if(arr[i]>arr[j]){
T temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
}
}
};
// 定义打印数组函数模板
template <typename P, size_t L>
void printArray(P (&arr)[L], string title){
cout <<title <<": ";
// 打印排序后的数组
for(size_t i = 0; i < L; ++i) {
cout << arr[i] << " ";
}
cout << endl;
};
int main(){
int nums[] = {65, 30, 15, 100, 5000};
printArray(nums, "print int before"); //打印排序前int数组结果
sortArray(nums); //排序int数组
printArray(nums, "print int after"); //打印排序后int数组结果
float nums2[] = {3.14f, 8.05f, 1.2f, 0.88f, 9.5f};
printArray(nums2, "print float before"); //打印排序前float数组结果
sortArray(nums2); //排序float数组
printArray(nums2, "print float after"); //打印排序后float数组结果
long nums3[] = {531138, 782323, 173884, 8813, 64388, 1953};
printArray(nums3, "print long before"); //打印排序前long数组结果
sortArray(nums3); //排序long数组
printArray(nums3, "print long after"); //打印排序后long数组结果
return 0;
}
运行结果如下:
此时不但在调用sortArray()函数时不用传入数组长度,在函数模板中也能直接获取到数组长度,方便了程序编写,提高效率。
不过这里需要注意是template中除了定义"typename T"外,还必须定义"size_t L",否则编译过程中会报错"[Error] 'L' was not declared in this scope"。
当然,在C++中获取数组长度还有其他方法,这里就先讲这些,希望对大家有帮助。