为什么在矩阵类的实现中触发了一个本地异常?

  • 本文关键字:一个 异常 实现 c++
  • 更新时间 :
  • 英文 :


我正在编写矩阵类的实现。复制操作符检查矩阵的大小是否匹配。如果你运行这个版本的程序:

Matrix<int> mat1(3,3);
Matrix<int> mat2(3,3);
mat1.fillMatrix();
mat2.fillMatrix();
Matrix<int> mat3 = mat1 - mat2;

一切都很好。但是如果你这样做

Matrix<int> mat1(3,3);
Matrix<int> mat2(3,3);
mat1.fillMatrix();
mat2.fillMatrix();
Matrix<int> mat3;//or Matrix<int> mat3(3,3)
mat3 = mat1 - mat2;

构造函数抛出一个异常,如下:

Matrix() : data(nullptr), rows(0), cols(0) {}
Matrix(size_t rows, size_t cols) : data(static_cast<T *>(operator new[](sizeof(T) * rows * cols, static_cast<std::align_val_t>(alignof(T))))), rows(rows), cols(cols) {}
Matrix &operator=(Matrix<T> &&other) noexcept
{
if (&other == this)
{
return *this;
}
if (rows != other.rows || cols != other.cols)
{
throw std::logic_error("Error assigning matrices of different sizes");
}
clean();
std::swap(data, other.data);
std::swap(rows, other.rows);
std::swap(cols, other.cols);
other.data = nullptr;
other.rows = 0;
other.cols = 0;
return *this;
}

我理解调用默认构造函数,它将行和列设置为0,因此抛出异常,但是为什么在第一种情况下一切都工作得很好,但在第二种情况下却不行?有可能解决这个问题吗?

使用SmallMatrix或Matrix获取类型安全的矩阵:

#include <cstddef>
#include <type_traits>
#include <cstring>
#include <initializer_list>
#include <utility>
#include <memory>
#include <cassert>
#include <algorithm>
template <typename T, std::size_t rows, std::size_t cols>
class SmallMatrix {
public:
const T * operator[](std::size_t x) const {
return data[x];
}
T * operator[](std::size_t x) {
return data[x];
}
T data[rows][cols]{};
};
template <typename T, std::size_t rows, std::size_t cols>
class Matrix {
private:
T *data{new T[rows * cols]};
public:
Matrix() { }
~Matrix() {
delete[] data;
data = nullptr; // crash on use after free
}
Matrix(const Matrix &other) {
*this = other;
}
Matrix(T &&other) : data(other.data) {
other.data = nullptr;
}
Matrix & operator=(const Matrix &other) {
if constexpr (std::is_aggregate_v<T>) {
memcpy(data, other.data, sizeof(T) * rows * cols);
} else {
for (std::size_t i = 0; i < rows; ++i) {
for (std::size_t j = 0; j < cols; ++j) {
(*this)[i][j] = other[i][j];
}
}
}
return *this;
}
Matrix operator=(Matrix &&other) {
swap(data, other.data);
return *this;
}
const T * operator[](std::size_t x) const {
return &data[x * cols];
}
T * operator[](std::size_t x) {
return &data[x * cols];
}
Matrix(const T (&other)[rows][cols]) {
if constexpr (std::is_aggregate_v<T>) {
memcpy(data, other, sizeof(T) * rows * cols);
} else {
for (std::size_t i = 0; i < rows; ++i) {
for (std::size_t j = 0; j < cols; ++j) {
(*this)[i][j] = other[i][j];
}
}
}
}
Matrix(T (&&other)[rows][cols]) {
if constexpr (std::is_aggregate_v<T>) {
memcpy(data, other, sizeof(T) * rows * cols);
} else {
for (std::size_t i = 0; i < rows; ++i) {
for (std::size_t j = 0; j < cols; ++j) {
std::swap((*this)[i][j], other[i][j]);
}
}
}
}
};
#include <iostream>
int main() {
Matrix a{{{1, 2}, {3, 4}}};
Matrix b{a};
Matrix<double, 5, 8> m;
std::cout << b[0][0] << " " << b[0][1] << std::endl;
std::cout << b[1][0] << " " << b[1][1] << std::endl;
}

相关内容

最新更新