不能将 int *(*)[] 转换为 int(**)[]

cannot cast int *(*)[] to int(**)[]

本文关键字:int 转换 不能      更新时间:2023-10-16
int main()
{
    int j;
    std::cin >> i >> j;
    int (**ptr)[1];
    ptr = new (int*[i][1]);//error
    for (int index = 0;index < i;++index)
        ptr[index] = new (int[j][1]);
}

我有一个编译器错误。

那么,如何分配int(**)[]

问题。

原始代码,除了我添加了缺少的 #include 指令——为了避免对您的代码的错误猜测以及讨论的不相关问题,请在发布的代码中包含所有内容

#include <iostream>
int main()
{
    int j;
    std::cin >> i >> j;
    int (**ptr)[1];
    ptr = new (int*[i][1]);//error
    for (int index = 0;index < i;++index)
        ptr[index] = new (int[j][1]);
}

使用 MinGW g++ 5.1.0 编译:

C:\my\forums\so\116> g++ --version | find "++">g++ (TDM64-1( 5.1.0C:\my\forums\so\116> g++ original.cpp原文.cpp:在函数'int main(('中:原始.cpp:5:17:错误:"i"未在此范围内声明     std::cin>> i>> j;                 ^原始.cpp:9:35:错误:ISO C++禁止可变长度数组 [-Wvla]         PTR[索引] = new (int[j][1](;                                   ^原始.cpp:9:36:错误:必须指定非常量数组新长度,类型ID [-Wvla] 周围必须不带括号         PTR[索引] = new (int[j][1](;                                    ^C:\my\forums\so\116> _

该编译器检测到以下问题:

  • 缺少变量i的声明。

  • 由于语法错误,无意中使用了 C99 可变长度数组 VLA。

使用 Visual C++ 2015 更新 2 进行编译:

C:\my\forums\so\116> cl/nologo- 2>&1 | 查找"++">Microsoft (R( C/C++ 优化编译器版本 19.00.23725 for x86C:\my\forums\so\116> cl original.cpp原创.cpp原始.cpp(5(: 错误 C2065: "i": 未声明的标识符原始.cpp(7(:错误 C2065:"i":未声明的标识符原始.cpp(7(: 错误 C2440:"=":无法从"int *(*([1]"转换为"int (**([1]"原文.cpp(7(:注:所指类型不相关;转换需要 reinterpret_cast、C 型转换或函数式转换原始.cpp(8(: 错误 C2065:"i":未声明的标识符C:\my\forums\so\116> _

此编译器不支持 C99 VLA,因此会诊断

  • 指针赋值中的类型不兼容。
显然,这是OP

关注的错误消息,但OP将其报告为:

"> 无法将 int (([] 转换为 int(**([]

这是没有意义的,因为确实可以在数据指针类型之间进行转换。

所以

  • 问题中的错误描述不正确。

  • 除了 OP 挑出的错误之外,代码还存在问题(缺少包含,缺少变量声明(。

  • 目前还不清楚代码的目的是做什么,除了在非常抽象的意义上允许诸如"使用std::vector"之类的建议。

但是,代码片段

for (int index = 0;index < i;++index)
    ptr[index] = new (int[j][1]);

强烈表明这是尝试使用用户指定的维度来执行int值的动态大小矩阵(2D 数组(,我在下面假设。


修复原始代码。

命名事物通常有帮助。在这种情况下,为清楚起见,我们可以将int*类型命名为 Int_array_ptr .这表示了预期的用途:不是作为指向单个int的指针,而是作为指向int数组第一项的指针,即作为指向数组的指针。

#include <iostream>
int main()
{
    int n_rows;
    int n_columns;
    std::cin >> n_rows >> n_columns;
    using Int_array_ptr = int*;
    Int_array_ptr* matrix;
    matrix = new Int_array_ptr[n_rows];     // An array of `n_rows` pointers.
    for( int i = 0; i < n_rows; ++i )
    {
        matrix[i] = new int[n_columns]();   // The `()` adds zero-initialization.
    }
    // At this point one can use it like `matrix[row][column] = 42`.
}

生成的结构称为交错数组,因为它允许列向量具有不同的长度(此处它们都是相同的长度(。


一般如何做矩阵。

矩阵作为交错数组的一个很好的替代方法是使用单个连续的一维数组作为存储,并且只提供对该数组的二维索引。

管理阵列存储的一个好方法是使用 std::vector

封装索引操作和其他数组内容(或公共状态上的大多数相关操作集(的一个好方法是定义一个类。

因此,这强烈建议定义一个类,该类在单个 1D 数组上提供 2D 索引操作,该数组的存储由 std::vector 管理。

理想情况下,索引是通过operator[],但作为一个成员操作,它只能接受1个参数。而且写起来有点麻烦,例如 matrix[Location(3,58)]而不是理想的matrix[3,58](这将被解析为使用逗号表达式(。因此,通常使用函数调用运算符operator()而不是[]

可以改为支持符号matrix[3][58],但让我们选择概念上更简单的operator()实现:

#include <iostream>
#include <vector>
#include <stdlib.h>     // EXIT_FAILURE
using namespace std;
class Matrix
{
private:
    vector<int>     items_;
    int             n_columns_;
    auto index_of( int const row, int const col ) const
        -> int
    { return row*n_columns_ + col; }
public:
    auto operator()( int const row, int const col )
        -> int&
    { return items_[index_of( row, col )]; }
    auto operator()( int const row, int const col ) const
        -> int
    { return items_[index_of( row, col )]; }
    Matrix( int const n_rows, int const n_columns )
        : items_( n_rows*n_columns )
        , n_columns_( n_columns )
    {}
};
auto main() -> int
{
    int n_rows;
    int n_columns;
    std::cin >> n_rows >> n_columns;
    if( cin.fail() ) { return EXIT_FAILURE; }
    Matrix matrix( n_rows, n_columns );
    // At this point one can use it like `matrix( row, column ) = 42`.
}

这比原始代码多得多,但是

  • 它是可重用的代码,可以节省工作,

  • 它是更健壮的代码,困难的事情(内存管理(自动化,并且

  • 它甚至可以更高效,因为它使用单个动态分配进行管理。

似乎您想分配二维数组。因此,分配应按以下方式完成:

int i, j;       // Initialize some value to i, j.
....
int **ptr = new int*[i];
for(int k = 0; k < i; k++) {
    ptr[k] = new int[j];
}   

这将创建一个具有 i 行和 j 列的二维数组。

您正在尝试分配一个int (*)[1]对象的数组。您已经注意到,像 new int(*)[1] 这样的语法不起作用,因为它被解析为new int后跟函数调用运算符,因此您必须使用 new(T) 形式。

此外,int *[i][1]是不对的,因为int *是指向 int 的。就像你在int (**ptr)[1]中所做的那样,你必须使用括号来打破int*

因此,正确的语法 new( int (*[i])[1] ) .但不幸的是,new(T)形式不允许在括号内包含非常量表达式!

技术信息:有一个专用的语法(C++14 [dcl.name]/1(用于sizeof(T)alignof(T)new(T)typeid(T)和强制转换的情况;它只允许方括号为空或在方括号内包含一个常量表达式。 对于new T情况([expr.new]/1((它知道[]但不知道(),并允许非常量表达式(,这两者都独立于在其他情况下解析声明符的语法。

所以唯一的解决方案(同时保留ptr的类型(是使用 typedef:

typedef int Arr1[1];
ptr = new Arr1 *[i];

每行为:

ptr[index] = new int[j][1];    // or "new Arr1[j];"

分配了一个指针数组,然后每个元素(指针(指向一个数组,如

int i = 20, j = 40;
int** ptr = new int*[i];
for (int a = 0; a < i; a++) {
    ptr[a] = new int[j];
    // ...
    delete [] ptr[a];
}
delete [] ptr;

编辑

返回您的代码

将类型 E 定义为 int[1] 时;

int j, i;
std::cin >> i >> j;
typedef int E[1];
E **ptr;                                // int (**ptr)[1];
ptr = new E*[i];                        // ptr = new (int*[i][1]);//error
for (int index = 0;index < i;++index)
    ptr[index] = new E[j];              // ptr[index] = new (int[j][1]);

所以只是一个指向整数指针的指针,不像你说的