MST

星途 面试题库

面试题:C++运算符重载三种方式性能比较之基础考察

请简述C++中运算符重载的三种方式(成员函数重载、友元函数重载、普通函数重载),并简单说明它们在性能上可能存在差异的原因。
30.4万 热度难度
编程语言C++

知识考点

AI 面试

面试题答案

一键面试

成员函数重载

  • 定义方式:将运算符重载函数定义为类的成员函数,其第一个参数(隐含的this指针所指对象)是运算符左侧的对象,其他参数为右侧对象。例如:
class Complex {
public:
    Complex(double real, double imag) : m_real(real), m_imag(imag) {}
    Complex operator+(const Complex& other) {
        return Complex(m_real + other.m_real, m_imag + other.m_imag);
    }
private:
    double m_real;
    double m_imag;
};
  • 性能特点:由于成员函数可以直接访问类的私有成员,在访问权限上较为直接高效。而且编译器在调用成员函数时,可以进行内联优化等常规优化,性能通常较好。

友元函数重载

  • 定义方式:在类中声明友元函数来重载运算符,友元函数不是类的成员,但可以访问类的私有成员。例如:
class Complex {
public:
    Complex(double real, double imag) : m_real(real), m_imag(imag) {}
    friend Complex operator+(const Complex& a, const Complex& b);
private:
    double m_real;
    double m_imag;
};
Complex operator+(const Complex& a, const Complex& b) {
    return Complex(a.m_real + b.m_real, a.m_imag + b.m_imag);
}
  • 性能特点:同样可以直接访问类的私有成员。由于友元函数与类的耦合度相对较低,编译器在某些情况下可能无法像对成员函数那样进行深度优化,不过实际性能差异通常不大。

普通函数重载

  • 定义方式:将运算符重载函数定义为普通的全局函数,不属于任何类。为了访问类的私有成员,需要类提供相应的接口。例如:
class Complex {
public:
    Complex(double real, double imag) : m_real(real), m_imag(imag) {}
    double getReal() const { return m_real; }
    double getImag() const { return m_imag; }
private:
    double m_real;
    double m_imag;
};
Complex operator+(const Complex& a, const Complex& b) {
    return Complex(a.getReal() + b.getReal(), a.getImag() + b.getImag());
}
  • 性能特点:由于不能直接访问类的私有成员,需要通过类提供的接口来获取数据,这可能会带来一些额外的开销。相比成员函数和友元函数,在频繁访问类数据成员时,性能可能会稍差。

性能差异原因总结

  1. 访问权限与优化:成员函数和友元函数能直接访问类的私有成员,编译器可以针对这种直接访问进行更有效的优化,如内联优化。而普通函数需要通过接口访问数据,编译器的优化空间相对受限。
  2. 函数调用开销:成员函数调用时,this指针的传递方式相对高效,且编译器熟悉类的结构,可做更多优化。普通函数调用时参数传递和函数查找的开销相对略高,虽然现代编译器在优化上已经很强大,但在极端情况下这种差异可能会体现出来。