【问题标题】:How to create a 2D array in C++ using this specific container如何使用此特定容器在 C++ 中创建二维数组
【发布时间】:2009-09-02 12:50:19
【问题描述】:

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

const ArrayRef<int> START_END_PATTERN_;
const ArrayRef<int> MIDDLE_PATTERN_;
const ArrayRef<ArrayRef<int> > L_PATTERNS_;
const ArrayRef<ArrayRef<int> > L_AND_G_PATTERNS_;

static int START_END_PATTERN[];
static int MIDDLE_PATTERN[];
static int L_PATTERNS[10][4];
static int L_AND_G_PATTERNS[20][4];
注意后面的下划线以区分这两个变量。

我不确定如何初始化二维 ArrayRef。我在这里发布的内容会出现段错误,因为这些 ArrayRef 正在堆栈上分配。有人有聪明的方法吗?

我真正设法让它工作的唯一方法是使用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;
  }
 }

【问题讨论】:

    标签: c++ arrays templates constructor class-template


    【解决方案1】:

    你所拥有的应该是安全的。 (分配的堆栈)ArrayRefs 创建分配给Arrays 的堆来支持它们,然后共享那些Arrays。

    编辑:感谢发帖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_constL_PATTERNS_[i] 调用来自ArrayRef&lt;ArrayRef&lt;int&gt; &gt; 的方法:

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

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

    有点令人惊讶的是ArrayRef 甚至允许这个赋值。当然它打破了“最小惊喜原则”。人们会期望编译器发出错误。为了保证编译器以后能更好的发挥作用,我们需要给ArrayRefoperator[] 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
    

    【讨论】:

    • 这就是我的想法,但由于某种原因,如果在该循环之后我尝试访问内部数组,它们会出现段错误。它给了我一个 EXEC_BAD_ACCESS 或类似的
    • 是的。我知道为什么。这是ArrayRef中的一个细微错误
    • Managu,非常感谢您对问题的详细检查和很好的解释。我错误地假设即使它是一个常量,如果我在构造函数列表中初始化它,然后在构造函数中初始化它,我仍然可以修改它。奇怪的是编译器不会抱怨它!我尝试了 const_cast,但得到以下错误:error: invalid use of const_cast with type 'common::ArrayRef&lt;common::ArrayRef&lt;int&gt; &gt;', which is not a pointer, reference, nor a pointer-to-data-member type 我也尝试将签名更改为第一个版本
    • 但结果如下:错误:将 'const common::ArrayRef' 作为 'common::ArrayRef& common::ArrayRef 的 'this' 参数传递: :operator=(const common::ArrayRef&) [with T = int]' 丢弃限定符`我认为这里的问题是即使它返回一个 const 对象,它也会尝试在分配,所以 L_PATTERNS_[i] 实际上不会被分配。在我看来,唯一的方法是让 L_PATTERNS_ 非 const ......以后有没有办法将它转换为 const ?
    • 多哈。现在没有资源来检查它,但我认为在const_cast 中添加一个“&”将解决我的解决方案。至于第二个错误——这就是意图。答案已更改为包含此信息。
    【解决方案2】:

    原因可能有多种。例如,您没有在粘贴中包含“Counted”类,并且在某些时候会调用 a->retain()(第 130 行)。此方法未显示。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-04-25
      • 1970-01-01
      • 2023-01-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多