30数组

数组:一个集合,一堆元素按照特定的顺序排列起来

#include <iostream> 


int main()
{
	int example[5];
	example[0] = 2;
	example[4] = 4;

	std::cout << example[0] << std::endl;
	//无效值
	std::cout << example[2] << std::endl;
	std::cout << example[4] << std::endl;
	//编译器不检查越界
	std::cout << example[-1] << std::endl;
	std::cout << example[5] << std::endl;
	//数组内存地址
	std::cout << example << std::endl;
	/*
2
-858993460
4
-858993460
-858993460
0000006DC77EFB38
	*/
	std::cin.get();
}

循环 #

#include <iostream> 


int main()
{
	int example[5];
	example[0] = 2;
	example[1] = 4;
	example[2] = 2;
	example[3] = 4;
	example[4] = 2;
	for (int i = 0; i < 5; i++)
	{
		example[i] = i;
	}
	std::cin.get();
}

如果,数组在内存中是连续的同类型数值

数组指针运算 #

数组实际上只是一个指针,它是一个整数,指向内存块的指针

#include <iostream> 

int main()
{
	int example[5];
	int* ptr = example;

	//这里根据指针指向数据类型的字节数来对地址运算(这里是2个(int)4字节)
	*(ptr + 2) = 6;
	//这行代码和上面是一个效果,都是对
	//第3个元素赋值
	*((char*)ptr + 8) = 7;
	 
	std::cin.get();
}

堆上创建数组 #

#include <iostream> 

int main()
{
	//在栈上创建数组
	int example[5];
	for (int i = 0; i < 5; i++)
		example[i] = 2;

	//在堆上创建数组
	int* another = new int[5];
	for (int i = 0; i < 5; i++)
		another[i] = 2;
	delete[] another;

	std::cin.get();
}

性能略有区别 #

#include <iostream> 

class Entity
{
public:
	int example[5];
	Entity()
	{
		for (int i = 0; i < 5; i++)
			example[i] = 2;
	}
};

int main()
{ 
	Entity e;
	std::cin.get();
}

直接在堆上创建的数组,直接根据数组地址就能查到数据

在栈上创建的数组,先根据数组地址得到另一个地址(8字节,数组只存储了堆上数组的地址),然后再根据该地址得到堆上数组

计算数组元素个数 #

#include <iostream> 
 
int main()
{ 

	int a[5];
	std::cout << sizeof(a) << std::endl;//20,数组大小(字节数)
	std::cout << sizeof(a)/sizeof(int) << std::endl;//5,数组个数

	int* example = new int[5];
	std::cout << sizeof(example) << std::endl;//8,指针的大小(8字节)
	

	std::cin.get();
}

这个计算方式在某些情况下是不可靠的,比如当该数组是作为函数参数时:

// 错误示例
void printSize(int arr[]) {
    // 这里 arr 实际上是指针,不是数组
    size_t size = sizeof(arr) / sizeof(int);  // ❌ 错误的!
    std::cout << "错误的大小: " << size << std::endl;
}

建议 #

错误 #

class Entity
{ 
	const int size = 5;
	
	//编译报错,原因是size可变,见下面的构造函数
	int arr[size];
	
	//注意,这里使用构造函数初始化就
	//可以在每次创建新对象时初始化const成员的值
	Entity(int s) : size(s) {}  // 构造函数可以修改 size

};

修正 #

class Entity
{ 
	static const int size = 5;
	
	//编译正常,因为这里是静态成员常量
	int arr[size];
	
};

其他建议 #

std::array::size(),C++11静态数组

#include <array>
std::array<int, 5> arr = {1, 2, 3, 4, 5};
size_t size = arr.size();  // ✅ 类型安全,不会出错

std::vector::size(),动态数组

#include <vector>
std::vector<int> vec = {1, 2, 3, 4, 5};
size_t size = vec.size();  // ✅ 动态大小

std::size() (C++17)

#include <iterator>  // C++17

int arr[] = {1, 2, 3, 4, 5};
size_t size = std::size(arr);  // ✅ 最简洁的方式

std::array<int, 5> stdarr = {1, 2, 3, 4, 5};
size_t size2 = std::size(stdarr);  // ✅ 也适用于 std::array

std::vector<int> vec = {1, 2, 3, 4, 5};
size_t size3 = std::size(vec);  // ✅ 也适用于 std::vector