数组表示法之间的差异

时间:2013-11-19 16:42:19

标签: c++ arrays syntax

以下表示法之间有什么区别?

int * arrayA = new int[5];
int arrayB[5];

我知道第一行会返回指针类型,而第二行会返回int[]类型 - 但内部会发生什么?我将如何以编程方式确定arrayA的元素数?

4 个答案:

答案 0 :(得分:4)

区别在于arrayB是一个具有自动存储持续时间的数组(如果它是局部变量,则在堆栈上为〜),而arrayA是指向具有动态存储的数组的第一个元素的指针持续时间(〜堆上)。

arrayB的元素数可以这样确定:

template <class T, size_t N>
size_t getElementCount(T (&)[N]) { return N; }

int main() {
  assert(getElementCount(arrayB) == 5);
}

可以确定arrayA的元素数。它不存储在程序可访问的任何位置。

答案 1 :(得分:3)

第一个动态分配内存。的一生 数组持续直到您明确释放它(delete [] arrayA;)。 在实践中,从来没有任何理由这样做;只是用 std::vector<int>(所以你不必担心 删除)。

第二个创建一个数组作为局部变量。它会停止 变量超出范围时存在。如果对某些人 你不能使用std::vector的原因,然后更喜欢这个解决方案。

关于数组的大小:在第一种情况下,它是 由你来管理它。就语言而言, 你只拥有一个指针。在第二种情况下,你可以得到 使用标准函数std::end( arrayA ) - std::begin( arrayA )的大小(至少在C ++ 11中)。或者,如果你是 将它传递给另一个函数,你可以通过引用传递它;如果 另一个函数是一个模板(例如template <size_t N> void func( int (&array)[N] )),编译器将使用它来实例化它 正确的尺寸。如果它不是模板(例如void func( int (&array)[5] )),则编译器会在大小不符合时进行投诉 正确的。

答案 2 :(得分:3)

我认为你的意思是

int arrayB[5];

而不是

int [5] arrayB;

因为最后一个不是合法的C ++声明。这种声明在C#中使用。

在这种情况下

int * arrayA = new int[5];

在堆中创建一个未命名的数组,并将该数组的第一个元素的地址分配给指针arrayA。变量arrayA对您分配的元素数量一无所知。例如,下面这两个变量具有相同的类型

int *array1 = new int[5];
int *array2 = new int[10];

在第二种情况下

int arrayB[5];

变量arrayB表示由int类型组成的5个元素。它有类型int [5]并且知道它有5个元素。例如,int [5]和int [10]是两种不同的类型。

答案 3 :(得分:3)

  

以下表示法之间有什么区别?

第一个分配动态数组并为您提供指向它的指针。当您不再需要时,您将需要删除该数组(delete [] p),否则内存将泄漏。通常最好不要使用原始指针来管理动态资源,因为确保它被正确删除是很棘手的。首选RAIIstd::vector<int>来自动管理资源。

第二个声明了声明出现在任何范围内的数组。如果这是在函数内部,它具有自动存储持续时间,并且当它超出范围时将自动销毁。如果它在函数外部,则它具有静态存储持续时间,并将在程序结束时自动销毁。

  

我如何以编程方式确定arrayB的元素数?

以C方式:

size_t arrayB_size = sizeof arrayB / sizeof arrayB[0];

或以C ++方式:

template <typename T, size_t N> size_t array_size(T(&)[N]) {return N;}
size_t arrayB_size = array_size(arrayB);

请注意,您无法确定动态数组的大小 - 该信息会丢失。第一种样式会产生伪造的结果(基于指针的大小而不是数组),第二种样式将无法编译。这是另一个让vector知道其大小的原因。