如何基于自定义my_vector类构建以向量为列的my_matrix类
问题
已实现具备标量积、加法、点积等功能的my_vector类,现需构建以my_vector作为列的my_matrix类,但动态分配内存时无法控制my_vector的维度。以下是完整的my_vector.h代码及未完成的my_matrix.h代码,寻求构造函数与析构函数的实现方案:
my_vector.h
#pragma once #include <cassert> #include <cmath> #include <cstddef> #include <initializer_list> #include <stdexcept> using namespace std; inline auto& lengtherr = "Not compatible"; template <typename T> class my_vector { private : size_t m_dim; T *m_arr; public: my_vector(size_t s = 0) : m_dim{s}, m_arr{new T[s]} {} my_vector(const my_vector &rhs) : m_dim{rhs.m_dim},m_arr{new T [rhs.m_dim]} { for(int i = 0 ; i<rhs.m_dim;++i)m_arr[i] = rhs.m_arr[i]; } my_vector(initializer_list<T> list): my_vector(list.size()) { m_dim = list.size(); int cnt = 0; for(auto i : list) m_arr[cnt++] = i; } ~my_vector() { delete[] m_arr; } size_t dim() const { return m_dim; } void operator=(const my_vector<T> &v) { if(v.dim()== m_dim) { for(int i = 0 ; i < m_dim;++i) m_arr[i] = v[i]; } else throw length_error(lengtherr); } T &operator[](size_t idx) { assert(idx<m_dim); return m_arr[idx]; } const T& operator[](size_t idx)const { assert(idx<m_dim); return m_arr[idx]; } T length() { T temp;temp = m_arr[0]*m_arr[0]; for(int i = 1 ; i< m_dim;++i)temp+= m_arr[i]*m_arr[i]; return sqrt(temp); } void normalize() { T len = 1/(this->length()); *this = *this * len; } };
my_matrix.h(未完成)
template<typename T> class my_matrix { size_t m_row{0}; size_t m_col{0}; public : my_vector<T> *m_mat; my_matrix(size_t r, size_t c) : m_row{r},m_col{c} { /*How do I construct??*/ } ~my_matrix() { /*destructor*/ } };
需求说明:创建以my_vector作为列的my_matrix,解决动态分配内存时的my_vector维度控制问题。
解决方案
构造函数实现
由于my_matrix以my_vector作为列,每个列向量的维度必须等于矩阵的行数m_row。但C++数组new只能调用默认构造函数(会创建0维度的my_vector),且原my_vector的赋值运算符会在维度不同时抛出异常,因此需要通过placement new直接在分配的内存中构造指定维度的向量:
my_matrix(size_t r, size_t c) : m_row{r}, m_col{c} { // 先分配原始内存,不调用my_vector构造函数 m_mat = static_cast<my_vector<T>*>(operator new[](m_col * sizeof(my_vector<T>))); // 逐个构造每个my_vector<T>,维度为m_row for (size_t i = 0; i < m_col; ++i) { new (&m_mat[i]) my_vector<T>(m_row); } }
析构函数实现
需要手动调用每个my_vector的析构函数,再释放分配的原始内存:
~my_matrix() { // 逐个调用my_vector的析构函数 for (size_t i = 0; i < m_col; ++i) { m_mat[i].~my_vector<T>(); } // 释放底层内存 operator delete[](m_mat); }
补充:避免浅拷贝的安全扩展
为了防止浅拷贝导致的内存泄漏或重复释放,建议补充实现拷贝构造、拷贝赋值、移动构造和移动赋值运算符:
// 拷贝构造函数 my_matrix(const my_matrix& other) : m_row{other.m_row}, m_col{other.m_col} { m_mat = static_cast<my_vector<T>*>(operator new[](m_col * sizeof(my_vector<T>))); for (size_t i = 0; i < m_col; ++i) { new (&m_mat[i]) my_vector<T>(other.m_mat[i]); // 调用my_vector拷贝构造 } } // 拷贝赋值运算符 my_matrix& operator=(const my_matrix& other) { if (this != &other) { // 销毁当前对象的向量 for (size_t i = 0; i < m_col; ++i) { m_mat[i].~my_vector<T>(); } operator delete[](m_mat); // 重新分配并构造 m_row = other.m_row; m_col = other.m_col; m_mat = static_cast<my_vector<T>*>(operator new[](m_col * sizeof(my_vector<T>))); for (size_t i = 0; i < m_col; ++i) { new (&m_mat[i]) my_vector<T>(other.m_mat[i]); } } return *this; } // 移动构造函数 my_matrix(my_matrix&& other) noexcept : m_row{other.m_row}, m_col{other.m_col}, m_mat{other.m_mat} { other.m_row = 0; other.m_col = 0; other.m_mat = nullptr; } // 移动赋值运算符 my_matrix& operator=(my_matrix&& other) noexcept { if (this != &other) { // 销毁当前对象 for (size_t i = 0; i < m_col; ++i) { m_mat[i].~my_vector<T>(); } operator delete[](m_mat); // 转移资源 m_row = other.m_row; m_col = other.m_col; m_mat = other.m_mat; other.m_row = 0; other.m_col = 0; other.m_mat = nullptr; } return *this; }
内容的提问来源于stack exchange,提问作者gunslinger
相关产品推荐
相关产品推荐

