【问题标题】:Compiler error while defining array using typeof and decltype使用 typeof 和 decltype 定义数组时出现编译器错误
【发布时间】:2016-02-14 22:57:15
【问题描述】:

A)这行得通:

int main() {
    int * a = new int[5];
    delete[] a;
    return 0;
}

B)这个错误出来了:

int main() {
    int * a = new typeof(*a)[5];
    delete[] a;
    return 0;
}

错误:数组下标的无效类型“int[int]”

C)这行得通:

int main() {
    int * a = new typeof(a)[5];
    delete[] a;
    return 0;
}

我不明白为什么 B 会失败,因为扩展后的语句应该是这样的:

int *a = new int[5];

因为typeof(*a) 是整数。

下面是 decltype 的实验:

D) 这不起作用:

int main() {
    int * a = new decltype(a)[5];
    delete[] a;
    return 0;
}

出现错误:无法在初始化中将“int**”转换为“int*”。鉴于 decltype(a) 是 int* ,因此这是意料之中的,因此它转换为不正确的 int *a = new int*[5];

E) 但这不起作用:

int main() {
    int * a = new decltype(*a)[5];
    delete[] a;
    return 0;
}

出现错误:new 不能应用于引用类型

因此,无论是 GCC 扩展还是标准 C++11 功能,在所有情况下似乎都没有按照我的预期工作。

【问题讨论】:

  • c++ 中没有typeof。如果您使用编译器扩展 - 您显然这样做了 - 然后说明您要询问的编译器。
  • 我收到了error: expected type-specifier before ‘typeof’ - 你的意思是写decltype吗?
  • @TobySpeight 这是一个 gcc 扩展。
  • @molbdnilo - 啊,所以-std=gnu++11 而不是-std=c++11;谢谢。

标签: c++ typeof decltype


【解决方案1】:

*a 是一个指向 int 的指针,所以不能这样调用 typeof

int *a = new int[5];

之所以有效,是因为您要显示整数并在 a 显示的位置声明大小为 5 的新数组

也许你想要:

typeof(new typeof(int *)[5])a;

改为

 int * a = new typeof(*a)[5];

【讨论】:

  • a 是指向int 的指针。 *ainttypeof(*x) 甚至是 gcc's examples 之一。
  • *a 不是指向 int 的指针。 *a 是 a 所指向的,一个 int。那么为什么它不起作用呢?我基本上想消除定义语句中提到的任何数据类型,并希望使用现有变量本身,因此您的建议 typeof(new typeof(int *)[5])a; 虽然正确,但不是我想要的。
  • int *s;类型 (*s)m[5]; s=m;
【解决方案2】:

或标准 C++11 功能,在所有情况下似乎都没有按照我的预期工作。

那么你有错误的期望 - 至少在 decltype 的情况下。我不知道 gcc 的 typeof 是如何工作的,所以我无法回答为什么 B) 有效但 C) 无效但 D) 和 E) 的行为符合标准。

D) 在本例中,decltype 的表达式为 aa 是变量的名称。换句话说,它是一个 id 表达式。在 id 表达式的情况下,decltype 解析为实体的类型。 a 的类型是 int*。因此new decltype(a)[5]; 构造了一个int* 的数组。因为a的类型不是int**,所以它不能指向int*的数组。

E) 在本例中,decltype 的表达式为 *a。表达式的类型 (T) 是 int。但是*a 不是变量的名称。它不是像 a 这样的 id 表达式。 *a 的值类别是左值。对于左值表达式,decltype 解析为T&,其中T 是表达式的类型。因此,decltype(*a)int&。不允许引用数组,因此不允许使用 new decltype(*a)[5]

这是标准(草案)的引述:

§ 7.1.6.2 [dcl.type.simple]

  1. 对于表达式 e , 表示的类型 decltype(e) 定义如下:

—— 如果 e 是一个不带括号的 身份表达 或无括号的类成员访问( 5.2.5 ), decltype(e) 是由 命名的实体的类型 e .如果没有这样的实体,或者如果 e 命名一组重载函数 ,则程序格式错误;

—— 否则,如果 e 是一个 xvalue, decltype(e) 是 T&& , 在哪里 吨 是类型 e ;

—— 否则,如果 e 是一个左值, decltype(e) 是 T& , 在哪里 吨 是类型 e ;

—— 否则, decltype(e) 是类型 e

这是正确的:

int * a = new std::remove_pointer<decltype(a)>::type[5];

还有这个:

int * a = new std::remove_reference<decltype(*a)>::type[5];

当然,这两者都非常复杂。如果您的目标是避免重复该类型,那么decltype 不是您应该寻找的工具。适合您需求的工具是auto

auto a = new int[5];

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-12-29
    • 1970-01-01
    相关资源
    最近更新 更多