首页 > 解决方案 > 如何更有效地使用模板在 C++ 中实现具有绑定检查的二维数组?

问题描述

现在我像这样实现它:

template <typename T>
class Array2D{
  private:
    T **pointer = nullptr;
    int n1, n2;
    class tmp{
        private:
            T* pointer;
            int n;
        public:
            tmp(T* p, int n):pointer(p),n(n){}
            T& operator[](unsigned int x){
                assert(x<n);
                return pointer[x];
            }
    };
  public:
    Array2D(int n, int m):n1(n), n2(m){
        pointer = new T *[n];
        for (int i = 0; i < n; i++)
            pointer[i] = new T[m];
    }
    ~Array2D(){delete[] pointer;}
    tmp&& operator[](unsigned int x){
        assert(x < n1);
        return move(tmp(pointer[x], n2));
    }
};

我觉得代码有点难看。我之所以使用 tmp 类,是因为如果直接在类 Array2D 中返回 T*,则无法检查第二维的反弹。所以我添加了一个名为temporary 的类。但是我觉得这个类的效率变得更糟了。有更好的解决方案吗?

还有一件事让我很困惑。我希望其他人只能以二维形式使用此类。我的意思是,如果你只对这个类的一个实例使用 [],你会得到一个错误。所以我把类 tmp 放在私有部分。但我发现它行不通。有解决办法吗?

标签: c++

解决方案


的存在tmp很好,任何编译器都会将这些临时实例优化掉。

[]无法强制阻止使用单个,但您可以通过使用[[nodiscard]]from 的返回值触发警告Array2D::operator[]

但是,您的实现中存在一个错误:您正在从operator[]. 做就是了:

tmp operator[](unsigned int x){
    assert(x < n1);
    return tmp(pointer[x], n2);
}

最后,您不应该经历手动管理存储生命周期的麻烦。实际上,那里已经存在其他几个错误:您的析构函数泄漏内存,并且您的类不遵守 5 规则,因此复制或分配Array2D' 将导致 UB。只需使用一个std::vector<std::vector<T>>,或者更好的(为了连续性)一个std::vector<T>你分成行的单个。

结束语:一旦您的代码工作并准备好展示,您可以在Code Review上走一走。


推荐阅读