C++ 在不使用双指针语法的情况下创建基于堆的二维数组?

C++ 在不使用双指针语法的情况下创建基于堆的二维数组?,c++,c++11,syntax,C++,C++11,Syntax,我需要声明一个2D数组作为类的成员变量。我不能使用STL(所以,没有向量),我被要求避免使用双/三指针。我希望能够使用下标符号引用此2D数组中的元素,例如arr[0][0]。由于数组的大小,还必须在堆上声明该数组 由于我的要求,关于StackOverflow的现有答案都不能满足我的需要 我一直想做的是: class MyClass { public: MyClass() : arr(new int[1000][2]) {} // other stuff here private:

我需要声明一个2D数组作为类的成员变量。我不能使用STL(所以,没有向量),我被要求避免使用双/三指针。我希望能够使用下标符号引用此2D数组中的元素,例如
arr[0][0]
。由于数组的大小,还必须在堆上声明该数组

由于我的要求,关于StackOverflow的现有答案都不能满足我的需要

我一直想做的是:

class MyClass {
 public:
  MyClass() : arr(new int[1000][2]) {}

  // other stuff here

 private:
  int arr[1000][2];
};

编译该类后,我得到的错误是“无法使用
int[1000][2]
类型的左值初始化
int*
类型的参数”。显然,我可以通过使用指针语法来解决这个问题,但是,如上所述,为了代码清晰,我被要求使用“数组语法”。我希望有一个更好的理解C++的人可以解释如何使用“数组语法”。p> 当您的类中有一个数组,并且您使用
new
创建该类的新实例时,该数组位于堆上。您仍然可以使用
arr[i][j]
访问阵列

为什么不这样做呢

class-myClass{
公众:
国际航空货运量[1000][2];
};
int main(){
myClass*测试=新的myClass;
对于(int i=0;i<1000;i++){
对于(int j=0;j<2;j++){
测试->arr[i][j]=5;
}
}
}

您可以使用两个类来实现这一点

类基数组{
公众:
int&运算符[](int x){返回this->arr[x];}
int运算符[](int索引)常量{返回this->arr[index];}
int-arr[2];
};
类myClass{
公众:
myClass(){}
~myClass(){}
BaseArray和运算符[](int-index){返回this->arr[index];}
BaseArray运算符[](int index)常量{返回this->arr[index];}
基阵列arr[1000];
};
可以选择使用模板使此类更具动态性

模板
类基数组{
公众:
类型和运算符[](int x){返回this->arr[x];}
类型运算符[](int-index)const{returnthis->arr[index];}
类型arr[arraySize];
};
模板
类myClass{
公众:
myClass(){}
~myClass(){}
BaseArray和运算符[](int-index){返回this->arr[index];}
BaseArray运算符[](int index)常量{返回this->arr[index];}
基阵列arr[dim1];
};
int main()
{
myClass myArray;
}
编辑
当您提供数组维度时
int arr[1000][2]变量将自动分配到堆栈中。如果数组需要完全动态,您可以使用双指针
int**arr={nullptr}并在构造函数中初始化它,如下所示

class-myClass{
公众:
myClass()
{
arr=新整数*[1000];
对于(int i=0;i<1000;++i)
arr[i]=新整数[2];
}
~myClass()
{
/*确保删除,否则可能会标记内存错误*/
对于(int i=0;i<1000;++i)
删除[]arr[i];
删除[]arr;
}
int**arr={nullptr};
};

当然,您可以在不使用双/三指针的情况下执行此操作。您甚至可以在不使用类声明中的任何指针的情况下执行此操作。但首先让我们看看更常见的方法。二维阵列是一维阵列的简单扩展

从标准方式开始,使用
向量
对1000 int/o的1D数组执行此操作。指针“
arr
”位于堆栈上,但指向堆上1000个整数的数组

class MyClass {
public:
    MyClass() : arr(new int[1000]) {}

private:
    int *arr;
};
元素是以通常的方式访问的。例如
arr[0]=42

将其扩展到堆中的2D数组是上述方法的简单扩展。 您需要将成员变量声明为指向1D数组的指针,而不是基本类型

class MyClass {
public:
    MyClass() : arr(new int[1000][2]) {}

private:
    int (*arr)[2];
};
类似地,您可以用通常的方式引用2D数组的元素:
arr[0][0]=42

最后,有一种方法完全消除了指针,除了新的
所需的指针。这里我们初始化一个引用。诀窍是在new中添加第三级,即
[1]
,以便
*new
返回一个实际的2D int数组对象。从结构上讲,它与上面的指针版本没有什么不同,但允许我们直接初始化对2D int数组的引用。这当然不是一个常见的习惯用法,所以我坚持使用ptr方法

class MyClass {
public:
    MyClass() : arr(*new int[1][1000][2]) {}
    ~MyClass() {delete[] arr;}
//private:  // to test
    int(&arr)[1000][2];
};


int main()
{
    MyClass obj;
    obj.arr[2][1] = 42;
}

为什么要使用
new
为固定大小的数组分配内存?1。重新实现
std::vector
你自己,2。使用它。
std::vector(1000)
然后需要指针<代码>int-arr[1000][2]在堆栈上,对此您无能为力。这可能是可能的,但取决于其他需求。好的多维矩阵实现使用1D内存缓冲区来避免缓存未命中,并根据用户传递的2D坐标计算缓冲区中的位置。