以下表示法之间有什么区别?
int * arrayA = new int[5];
int arrayB[5];
我知道第一行会返回指针类型,而第二行会返回int[]
类型 - 但内部会发生什么?我将如何以编程方式确定arrayA
的元素数?
答案 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
),否则内存将泄漏。通常最好不要使用原始指针来管理动态资源,因为确保它被正确删除是很棘手的。首选RAII类std::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
知道其大小的原因。