You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何基于自定义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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.03 01:10:03