参考:
C++ 静态数组([])和动态数组(new)的区别
C++对数组的引用实例分析
存储和运行方式new
new在堆分配空间,效率较低,还需要你delete;
[]直接在栈上分配,会自动释放,效率高,但是栈空间有限。
使用sizeof运算
int a[5];
sizeof(&a)=4;
//int a[5];在编译阶段分配空间
//sizeof(a);同样在编译阶段执行
sizeof(a)=5*4;
sizeof(*a)=4;
//因为整个数组共占20字节
//首个元素(int型)占4字节。
//同理
int a[4][5];
sizeof(&a)=4;
sizeof(a)=4*5*4=80;
sizeof(a[0])=5*4=20;
sizeof(a[0][0])=4;
int *a=new int[4];
//int *a=new int[4];在运行分配空间
//sizeof(a);只在编译阶段执行,所以只能得到指针大小为4
sizeof(a)=sizeof(*a)=4
//因为地址位数为4字节
//int型也占4字节。
作为函数形参
数组引用会检查数组维数
//正确
int a[10] ;
int (&b)[10] = a ;
//错误:cannot convert from 'int [10]' to 'int *&'。
int a[10] ;
int* &b = a ;
数组作为参数传递会进行“数组降价”
即编译器对数组的维数不作检查
#include <iostream>
//void test( char arr[100] ) 等同于 void test( char arr[] )
//也等同于void test( char* const arr )
//所以你甚至可以往数组内传递arr[20]
void test( char arr[100] )
{
std::cout << sizeof(arr) << std::endl ; // 输出 4
}
void main()
{
char arr[100] = { 0 };
std::cout << sizeof(arr) << std::endl; // 输出 100
test( arr );
}
避免参数传递而导致“数组降价”的方法1:
......
//使用常量引用数组,但这样数组长度就只能固定不动了
void test( const char (&arr)[100] )
{
std::cout << sizeof(arr) << std::endl ; // 输出 100
}
......
char arr[100] = { 0 };
std::cout << sizeof(arr) << std::endl; // 输出 100
test( arr );
......
//错误!
char arr[20] = {0};
test( arr ) ;
避免参数传递而导致“数组降价”的方法2:
//虽然使用模板可以使数组长度可变,但是有以下问题:
//1.当有多个不同的test调用时,会产生多份test代码。
// 而传统的函数调用只有一份代,也调用的次数无关。
//2.不能传入动态分配的指针变量,因为模板函数在编译阶段
// 就需要确定数组的大小,从而生成代码,而指针变量
// 是在运行阶段才得以执行
template <int sz>
void test(char (&arr)[sz])
{
for ( int i = 0; i < sz; i++ )
......}
char a[2] = { 0 }, b[15] = { 0 };
test(a); //正确
test(b); //正确
作为函数返回值
函数声明的静态数组不可能通过函数返回,因为生存期的问题,函数调用完其内部变量占用的内存就被释放了。如果想通过函数返回一个数组,可以在函数中用new动态创建该数组,然后返回其首地址。
其原因可以这样理解,因为[]静态数组是在栈中申请的,而函数中的局部变量也是在栈中的,而new动态数组是在堆中的分配的,所以函数返回后,栈中的东西被自动释放,而堆中的东西如果没有delete不会自动释放。
//正确
int* test(){
int* b = new int[5];
return b;
}
//错误
int* test(){
int b[5];
return b;
}