我想知道为什么新的似乎没有保留数组信息并只返回一个int *:
#include <iostream>
using namespace std;
typedef int (*p_to_array)[80];
typedef int arr[80];
int main()
{
arr a;
p_to_array p = &a; //fine
p_to_array p2 = new arr; // incompatible types
return 0;
}
答案 0 :(得分:6)
我可能完全错了:(即这只是一个有根据的猜测)
new arr;
相当于:
new int[80];
按语言规则返回int*
。
来自cppreference.com :(感谢@interjay指出我实际上引用了无关的部分)
new-expression返回一个指向构造对象的prvalue指针,或者,如果构造了一个对象数组,则返回指向数组初始元素的指针。
我对此的理解是,在分配数组时,将选择new[]
表单。你的例子唯一改变的是语法;它没有使语言将数组视为非数组(常规对象)。
答案 1 :(得分:4)
您可以使用数组语法或typedef-name来分配带new
的数组 - 根据[expr.new] / 5允许和等效:
当分配的对象是一个数组时(即, 使用 noptr-new-declarator 语法或 new-type-id 或 type-id 表示数组类型), new-expression 产生指向的数据 数组的初始元素(如果有)。
如您所见,对于数组,只给出了指向初始元素的指针;不是指向数组对象本身的指针。因此,产生的类型为int*
,而不是int (*)[N]
。
返回指向初始元素的指针的原因非常简单:它是您要使用的指针。
我们想写
auto p = new int[50];
// Or
int* p = new int[50];
以便能够使用普通的下标:
p[49] = 0xDEADBEEF;
如果p
类型为int(*)[50]
指向数组对象,那将是荒谬的,因为下标会将49 * 50 * 4添加到地址,而不只是49 * 4 - 因为下标语义和指针算法
我们必须使用两个下标:
p[0][49] = ...;
这是可怕的,不必要的多余。或者我们可以使用演员:
int* p = static_cast<int*>(new int[50]); // Or with auto
但这也很难看 为了避免这种麻烦,引入了这条规则。
答案 2 :(得分:1)
在此声明中
p_to_array p2 = new arr; // incompatible types
初始值设定项new arr;
的类型与变量p2
初始化程序的类型是int *
,初始化程序是指向已分配数组的初始元素的指针。根据typedef定义,变量p2
的类型为int (*p_to_array)[80]
。
没有从int *
类型到类型int (*p_to_array)[80]
的隐式转换。所以编译器发出错误。
正确的声明可以查看以下方式
p_to_array p2 = new arr[1];