如何正确复制包含std::vector成员的Matrix类?
Matrix类拷贝构造函数未正确复制元素问题修复
问题描述
实现了一个以std::vector为底层容器的Matrix类,使用拷贝构造函数复制对象后,复制出的矩阵元素全为0,无法得到预期的与原矩阵相同的0-8整数矩阵。
原始代码
matrix.h
#ifndef MATRIX_H #define MATRIX_H #include <vector> #include <iostream> template <typename T> class Matrix { private: int m_rows; int m_cols; std::vector<T> m_vector; public: // Constructor Matrix(int rows, int cols) : m_rows{ rows }, m_cols{ cols } { m_vector.reserve(rows * cols); std::cout << "Constructor. vector capacity = " << m_vector.capacity() << '\n'; } // Copy constructor Matrix(const Matrix<T>& old) : m_rows{ old.m_rows }, m_cols{ old.m_cols } { m_vector.reserve(old.m_rows * old.m_cols); m_vector = old.m_vector; std::cout << "Copy constructor. vector capacity = " << m_vector.capacity() << '\n'; } const T& operator()(int row, int col) const { return m_vector[row * m_cols + col]; } T& operator()(int row, int col) { return m_vector[row * m_cols + col]; } } #endif // MATRIX_H
main.cpp
#include "matrix.h" int main() { // Create new matrix and fill Matrix<int> matrix(3, 3); int count = 0; for (int i = 0; i < 3; i++) { for (int j = 0; j < 3; j++) { matrix(i, j) = count++; } } // Print new matrix for (int i = 0; i < 3; i++) { for (int j = 0; j < 3; j++) { std::cout << matrix(i, j) << ' '; } std::cout << '\n'; } std::cout << '\n'; // Copy assignment and print new Matrix<int> matrix2(matrix); for (int i = 0; i < 3; i++) { for (int j = 0; j < 3; j++) { std::cout << matrix2(i, j) << ' '; } std::cout << '\n'; } std::cout << '\n'; return 0; }
问题根源
- 构造函数的错误使用:构造函数中调用
m_vector.reserve(rows * cols)仅为vector预留了内存空间,但vector的size仍为0。后续直接通过operator()赋值时,属于越界访问vector元素,是未定义行为。此时原matrix的vector实际上并没有真正存储这些值(size还是0),只是数据写到了预留的内存区域。 - 拷贝构造函数无效:由于原matrix的vector
size为0,执行m_vector = old.m_vector时,只会复制一个空vector,导致matrix2访问的也是越界位置,输出0或随机值。 - 语法错误:类定义结束后缺少分号,会导致编译失败。
修复方案
修改后的matrix.h
#ifndef MATRIX_H #define MATRIX_H #include <vector> #include <iostream> template <typename T> class Matrix { private: int m_rows; int m_cols; std::vector<T> m_vector; public: // 构造函数:直接初始化vector的size为rows*cols,确保元素可合法访问 Matrix(int rows, int cols) : m_rows{ rows }, m_cols{ cols }, m_vector(rows * cols) { std::cout << "Constructor. vector size = " << m_vector.size() << ", capacity = " << m_vector.capacity() << '\n'; } // 拷贝构造函数:利用vector的拷贝构造函数直接初始化,无需手动reserve Matrix(const Matrix<T>& old) : m_rows{ old.m_rows }, m_cols{ old.m_cols }, m_vector(old.m_vector) { std::cout << "Copy constructor. vector size = " << m_vector.size() << ", capacity = " << m_vector.capacity() << '\n'; } const T& operator()(int row, int col) const { return m_vector[row * m_cols + col]; } T& operator()(int row, int col) { return m_vector[row * m_cols + col]; } }; // 补上类定义结束的分号 #endif // MATRIX_H
修复说明
- 构造函数中通过成员初始化列表直接创建
m_vector(rows * cols),让vector的size和capacity都设置为rows*cols,后续赋值操作合法,vector会正确记录元素数量。 - 拷贝构造函数简化为直接调用vector的拷贝构造函数,自动完成所有元素的复制,无需手动预留空间。
- 补上类定义后的分号,修复语法错误。
内容的提问来源于stack exchange,提问作者Frederik Randrup
相关产品推荐
相关产品推荐

