uflyjz
2021-08-20 17:30
采纳率: 62.5%
浏览 64

试图实现二维数组类,出现““this”不能在常量表达式中使用”报错


class Array2
{
    int row, col;
    int (*p)[];

public:
    Array2(int row_ = 0, int col_ = 0) : row(row_), col(col_)
    {
        p = new int[row][col];
    }
};

vscode在new那行的col处波浪线提示“this”不能在常量表达式中使用,试图编译则会报错:error: only the first dimension of an allocated array may have dynamic size
p = new int[row][col];
^~~
note: implicit use of 'this' pointer is only allowed within the evaluation of a call to a 'constexpr' member function

我该怎么写以实现根据构造函数参数new处连续空间?

  • 收藏

1条回答 默认 最新

  • include_iostream_ 2021-08-20 18:40
    已采纳

    如果写成“int (*p)[]”的话,编译器必须能够在编译期推导p数组的长度才行,这个写法不等于变长数组,仅仅是让编译器自行推导长度而已。最常见的推导方式是直接给初始化数据。因此,你这个动态定长度的做法是不行的。如果是C++,可以用std::vector<std::vector<int> >做到这个效果,或者用int **p进行多次new也可以,但那样比较麻烦。
    ==== 分割线 ====
    根据问题更新,下面是一个带解释的解法:

    class Array2 {
        int r, c;
        int *p;
    public:
        Array2(int r, int c) : r(r), c(c) { // 比较优雅的方式是使用size_t,并通过异常机制报告错误参数
            p = new int[r * c];
        }
        Array2() : r(0), c(0), p(nullptr) { } // 占位符。比较优雅的方式是通过异常机制进行容错检查,但鉴于本题甚至不提供stdexcept于是作罢
        ~Array2() { // 好习惯:及时回收空间 
            if (p) delete[] p;
        }
        int& operator()(int i, int j) { // 圆括号访问机制
            return p[c * i + j]; // 二维数组偏移量机制:i行j列的元素相对于数组基址的偏移是c * i + j(字节偏移则要乘一个sizeof(value_type))
        }
        int* operator[](int i) { // 这里有点tricky,当使用类似a[i][j]的语法时,第一个方括号是调用本函数返回一个指针,第二个方括号则是原生语义 
            return p + c * i; // 和二维数组偏移机制同理,但第二个方括号由原生语义处理,我们重载的方括号运算符只负责返回第i行的一维数组,所以跟j没关系 
        }
        Array2& operator=(const Array2& another) { // 值得注意的是,C++赋值的原生语义就是返回引用,自定义类中最好保持相同的习惯
            if (p) delete[] p; // 记得释放之前的空间,虽然本题不这样写也无所谓
            r = another.r;
            c = another.c;
            p = new int[r * c]; // 题目没说是要深拷贝还是浅拷贝,这里是按深拷贝来做的,但本题做浅拷贝也可以有相同效果
            memcpy(p, another.p, r * c * sizeof(int)); // 深拷贝时记得对所有指针做内存复制操作,不能简单赋值 
        }
    };
    

    补充:上文提到r行c列二维数组的第i行第j列元素字节偏移是sizeof(value_type) * (i * c + j),这个结论成立的前提是:数组模型是按照从第一维存到最后一维的,也即每个靠前的维度的每个分量是连续的,在二维数组中表现为先行后列,但也有些语言的数组模型是先列后行。简单套用这个公式是不对的,尽管许多现代语言都有着和C++类似的先行后列的数组模型,但绝非所有语言都是如此。数组的具体存储方式和语言有关,和其他因素通常无关。在本题中表现为:如果在C++中使用先列后行的存储方式,那么方括号访问方式就不得不通过再封装一个内部类来实现,比较麻烦,但也不是做不到。

    已采纳该答案
    打赏 评论

相关推荐 更多相似问题