c++ - 如何使用此特定容器在 C++ 中创建二维数组

标签 c++ arrays templates constructor class-template

我正在尝试移植一个
int a[][]
从 Java 到 C++。我正在使用此类作为容器 ArrayRef对于整数,因为它处理引用,并且该项目广泛使用它。在我声明的 AbstractReader 类中

<code>const ArrayRef<int> START_END_PATTERN_;</code><br/> <code>const ArrayRef<int> MIDDLE_PATTERN_;</code><br/> <code>const ArrayRef<ArrayRef<int> > L_PATTERNS_;</code><br/> <code>const ArrayRef<ArrayRef<int> > L_AND_G_PATTERNS_;</code><br/>

<code>static int START_END_PATTERN[];</code><br/> <code>static int MIDDLE_PATTERN[];</code><br/> <code>static int L_PATTERNS[10][4];</code><br/> <code>static int L_AND_G_PATTERNS[20][4];</code><br/> 请注意结尾的下划线以区分这两个变量。

我不确定如何初始化二维 ArrayRef。我在这里发布的内容会出现段错误,因为那些 ArrayRefs 是在堆栈上分配的。谁有聪明的方法来做到这一点?

我实际设法让它工作的唯一方法是使用 ArrayRef< Ref<ArrayRef<int> > >通过使 ArrayRef 继承自 Counted,这基本上是一个允许在 C++ 中进行引用计数的类。但是为了访问元素,我必须执行类似 *(foo[i])[j] 的操作,这比 foo[i][j] 稍微麻烦一些。

int AbstractReader::L\_AND\_G_PATTERNS[20][4] = {

 {3, 2, 1, 1}, // 0
 {2, 2, 2, 1}, // 1
 {2, 1, 2, 2}, // 2
 {1, 4, 1, 1}, // 3
 {1, 1, 3, 2}, // 4
 {1, 2, 3, 1}, // 5
 {1, 1, 1, 4}, // 6
 {1, 3, 1, 2}, // 7
 {1, 2, 1, 3}, // 8
 {3, 1, 1, 2},  // 9
 // G patterns

 {1, 1, 2, 3}, // 0
 {1, 2, 2, 2}, // 1
 {2, 2, 1, 2}, // 2
 {1, 1, 4, 1}, // 3
 {2, 3, 1, 1}, // 4
 {1, 3, 2, 1}, // 5
 {4, 1, 1, 1}, // 6
 {2, 1, 3, 1}, // 7
 {3, 1, 2, 1}, // 8
 {2, 1, 1, 3}  // 9
 };

 AbstractReader::AbstractReader() 
 : decodeRowStringBuffer_(ostringstream::app),
 START_END_PATTERN_(START_END_PATTERN, 3),
 MIDDLE_PATTERN_(MIDDLE_PATTERN, 5),
 L_PATTERNS_(10),
 L_AND_G_PATTERNS_(20) {

  for (int i = 0; i < 20; i++) {
   if (i < 10) {
    L_PATTERNS_[i] = ArrayRef<int> ((L_PATTERNS[i]), 4);
   }
   ArrayRef<int> lgpattern((L_AND_G_PATTERNS[i]), 4);
   L_AND_G_PATTERNS_[i] = lgpattern;
  }
 }

最佳答案

您所拥有的应该是安全的。 (堆栈分配)ArrayRef s 创建分配的堆 Array让我们支持他们,然后分享那些Array

编辑:感谢您发帖 Counted .做了一些工作,但我想我知道发生了什么。

解决方案:不声明L_PATTERNS_L_AND_G_PATTERNS_作为const .或者,const_cast得到想要的operator[] .例如

const_cast<ArrayRef<ArrayRef<int> > &>(L_PATTERNS_)[i] = ArrayRef<int> ((L_PATTERNS[i]), 4);

理由: 在 AbstractReader ,你声明:

const ArrayRef<ArrayRef<int> > L_PATTERNS_;

然后在它的构造函数中,你尝试赋值:

AbstractReader::AbstractReader() :
{
    ...
    L_PATTERNS_[i] = ArrayRef<int> ((L_PATTERNS[i]), 4);
    ...
}

L_PATTERNS_const , L_PATTERNS_[i]ArrayRef<ArrayRef<int> > 调用一个方法:

T operator[](size_t i) const { return (*array_)[i]; }

这将返回 L_PATTERNS_[i] 处内容的全新拷贝.然后分配发生(进入临时),保持原始不变。当您稍后返回访问时 L_PATTERNS_[ xxx ] ,您正在查看原始的、未初始化的值(这是一个 NULL 引用/指针)。因此出现了段错误。

有点令人惊讶的是 ArrayRef甚至允许这个任务。当然,它打破了“最小惊喜原则”。人们会期望编译器发出错误。为了确保编译器在未来更有帮助,我们需要对 ArrayRef 给出一个稍微不同的定义。的 operator[] const (Array.h:121),如:

const T operator[](size_t i) const { return (*array_)[i]; }

或者可能(注意事项):

const T& operator[](size_t i) const { return (*array_)[i]; }

进行任何更改后,编译器都不允许分配。例如,GCC 报告:

error: passing 'const common::ArrayRef<int>' as 'this' argument of 'common::ArrayRef<T>& common::ArrayRef<T>::operator=(const common::ArrayRef<T>&) [with T = int]' discards qualifiers

关于c++ - 如何使用此特定容器在 C++ 中创建二维数组,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1367513/

相关文章:

c++ - 有没有办法确定顶级 Qt 窗口是否已移动?

c++ - 我应该在源文件中包含包含命名空间定义的 header 吗?

Java - 返回 2 个值(字符串数组)

c - 为什么要检查函数中 fscanf 返回值 < 1?

wpf - 在哪里可以找到免费的 WPF 控件和控件模板?

C++从迭代器中获取整数索引值

c++ - 避免枚举作为接口(interface)标识符 C++ OOP

c++ - 共享库中的内部异常终止最终用户应用程序

c++ - 如果递归函数定义为内联会发生什么?

java - Java中有序数组的索引