MST

星途 面试题库

面试题:C++运算符重载性能在复杂场景下的分析

假设有一个自定义的大型矩阵类Matrix,实现矩阵的加法运算符重载。请分别使用成员函数重载、友元函数重载、普通函数重载三种方式来实现,并分析在频繁进行矩阵加法运算时,哪种方式性能更优,为什么?同时说明如何对性能较差的实现方式进行优化。
34.5万 热度难度
编程语言C++

知识考点

AI 面试

面试题答案

一键面试

成员函数重载

class Matrix {
private:
    int** data;
    int rows;
    int cols;
public:
    Matrix(int r, int c) : rows(r), cols(c) {
        data = new int*[rows];
        for (int i = 0; i < rows; ++i) {
            data[i] = new int[cols];
            for (int j = 0; j < cols; ++j) {
                data[i][j] = 0;
            }
        }
    }
    ~Matrix() {
        for (int i = 0; i < rows; ++i) {
            delete[] data[i];
        }
        delete[] data;
    }
    Matrix operator+(const Matrix& other) const {
        Matrix result(rows, cols);
        for (int i = 0; i < rows; ++i) {
            for (int j = 0; j < cols; ++j) {
                result.data[i][j] = data[i][j] + other.data[i][j];
            }
        }
        return result;
    }
};

友元函数重载

class Matrix {
private:
    int** data;
    int rows;
    int cols;
public:
    Matrix(int r, int c) : rows(r), cols(c) {
        data = new int*[rows];
        for (int i = 0; i < rows; ++i) {
            data[i] = new int[cols];
            for (int j = 0; j < cols; ++j) {
                data[i][j] = 0;
            }
        }
    }
    ~Matrix() {
        for (int i = 0; i < rows; ++i) {
            delete[] data[i];
        }
        delete[] data;
    }
    friend Matrix operator+(const Matrix& a, const Matrix& b);
};
Matrix operator+(const Matrix& a, const Matrix& b) {
    Matrix result(a.rows, a.cols);
    for (int i = 0; i < a.rows; ++i) {
        for (int j = 0; j < a.cols; ++j) {
            result.data[i][j] = a.data[i][j] + b.data[i][j];
        }
    }
    return result;
}

普通函数重载

class Matrix {
private:
    int** data;
    int rows;
    int cols;
public:
    Matrix(int r, int c) : rows(r), cols(c) {
        data = new int*[rows];
        for (int i = 0; i < rows; ++i) {
            data[i] = new int[cols];
            for (int j = 0; j < cols; ++j) {
                data[i][j] = 0;
            }
        }
    }
    ~Matrix() {
        for (int i = 0; i < rows; ++i) {
            delete[] data[i];
        }
        delete[] data;
    }
    int get(int i, int j) const { return data[i][j]; }
};
Matrix operator+(const Matrix& a, const Matrix& b) {
    Matrix result(a.getRows(), a.getCols());
    for (int i = 0; i < a.getRows(); ++i) {
        for (int j = 0; j < a.getCols(); ++j) {
            result.data[i][j] = a.get(i, j) + b.get(i, j);
        }
    }
    return result;
}

性能分析

在频繁进行矩阵加法运算时,成员函数重载和友元函数重载的性能基本相同且相对较好。因为这两种方式都可以直接访问类的私有成员,避免了通过接口函数(如普通函数重载中的get函数)间接访问带来的额外开销。普通函数重载性能较差,因为每次访问矩阵元素都需要调用get函数,增加了函数调用的开销。

性能较差方式的优化

  1. 内联函数:将get函数声明为inline,这样在编译时函数调用会被替换为函数体的代码,减少函数调用开销。
  2. 直接访问成员:如果可能,修改普通函数重载的实现,让普通函数也能直接访问矩阵类的私有成员,这样就和成员函数、友元函数一样高效。可以通过将普通函数声明为类的友元来实现直接访问私有成员。
class Matrix {
private:
    int** data;
    int rows;
    int cols;
public:
    Matrix(int r, int c) : rows(r), cols(c) {
        data = new int*[rows];
        for (int i = 0; i < rows; ++i) {
            data[i] = new int[cols];
            for (int j = 0; j < cols; ++j) {
                data[i][j] = 0;
            }
        }
    }
    ~Matrix() {
        for (int i = 0; i < rows; ++i) {
            delete[] data[i];
        }
        delete[] data;
    }
    friend Matrix operator+(const Matrix& a, const Matrix& b);
};
Matrix operator+(const Matrix& a, const Matrix& b) {
    Matrix result(a.rows, a.cols);
    for (int i = 0; i < a.rows; ++i) {
        for (int j = 0; j < a.cols; ++j) {
            result.data[i][j] = a.data[i][j] + b.data[i][j];
        }
    }
    return result;
}