C++ C++;检查数组';通过引用传递时的大小

C++ C++;检查数组';通过引用传递时的大小,c++,arrays,memory,C++,Arrays,Memory,通过引用将数组传递给函数时,例如: void Foo(double (&MyList)[3]); 当您尝试将大小不同于3的数组传递给此函数时,代码不会编译。 根据我在C++中已经了解的,一旦实例化数组,就不可能知道数组的大小。 编译器如何跟踪数组的大小? 那么,如果它能够检查数组的大小,为什么这样的代码仍然可以编译呢 int MyTab[3] MyTab[3] = 5; C++只能跟踪具有自动或静态存储持续时间(即本地或全局变量)的数组的大小,因为这是唯一存在固定大小数组的地方(因此

通过引用将数组传递给函数时,例如:

void Foo(double (&MyList)[3]);
当您尝试将大小不同于3的数组传递给此函数时,代码不会编译。 根据我在C++中已经了解的,一旦实例化数组,就不可能知道数组的大小。 编译器如何跟踪数组的大小? 那么,如果它能够检查数组的大小,为什么这样的代码仍然可以编译呢

int MyTab[3]
MyTab[3] = 5;

C++只能跟踪具有自动或静态存储持续时间(即本地或全局变量)的数组的大小,因为这是唯一存在固定大小数组的地方(因此数组类型的变量只能引用这些数组)。令人困惑的是,数组被允许衰减为指针,这种情况可能会很快发生(例如,如果您将数组作为函数参数传递,而没有将参数作为引用传递给数组)

关于你的

int MyTab[3];
MyTab[3] = 5;
例如,让我们引用:

内置的下标表达式E1[E2]与 表达式*(E1+E2)

翻译成你的情况:

MyTab[3]
*(MyTab+3)
相同,我们可爱的指针又来了。
操作符+
对指针和整数进行操作,因此
MyTab
再次衰减为指针,丢失其所有大小信息

除此之外,您仍然可以通过越界访问获得结束迭代器(您只是不允许读取或写入值):


编译器确实可以警告您进行更大的越界访问,但不确定它为什么不这样做。

它没有。这就是为什么在C和C++中破坏内存很容易。所有这些问题都可以通过使用<代码> STD::向量< /代码>来补救。
std::vector
具有
size
成员函数。
std::vector
可以通过引用传递,并且可以使用运算符
[]
。@Dai:编译器确实跟踪数组大小。。。。usually@Dai:除了。。。“当通过引用将数组传递给函数时,例如:
voidfoo(double(&MyList)[3]);
”,这个问题就是关于这个函数的。在本例中,它不会衰减为指针类型,因为您传递的是引用,而不是数组。如果传递了错误的大小,这将导致所有编译器出现硬编译器错误。@Dai编译器确实知道大小<代码> int [3 ] < /> >是一个与EG <代码> int [4 ] < /COD>不同的数组,不是指针。C++只能跟踪位于堆栈上的数组的大小,因为这是数组类型变量存在的唯一地方。“-关于代码> CaloC(123,sieof(char))< /Cord>?@ DA:即使在这种情况下,C++也不跟踪大小。免费存储本身就是这样。一种解决方法是使用
std:array
例如
auto*parray=new std::array
它占用相同的存储量,但现在编译器知道它有多少个元素。但在大多数情况下,
std::vector
更好。
int i[] = new int[10];  // i is not an array, it's a pointer
int i[10];              // i is an array, the array is located on the stack
int MyTab[3];
MyTab[3] = 5;
int* begin = MyTab;   // pointer decay again, equal to &MyTab[0]
int* end = &MyTab[3]; // get a pointer to one past the end (aka end iterator)