繁体   English   中英

成员与非成员函数,返回副本还是引用?

[英]Member vs non-member functions, return copy or reference?

对于什么样的返回类型成员函数和非成员函数应该有什么“规则”?

我正在构建一个复杂类,我认为成员函数将是返回类型引用,而非成员将是副本。 这个对吗?

Complex.h供参考:

#include <iostream>
#include <string>

#ifndef COMPLEX_H
#define COMPLEX_H


class Complex {

  public:
    double real;
    double imaginary;


    Complex();
    Complex(const double real);
    Complex(const double real, const double imaginary);
    Complex(const Complex &rhs);

    Complex& operator *= (const Complex&);
    Complex& operator += (const Complex&);
    Complex& operator /= (const Complex&);
    Complex& operator -= (const Complex&);
    Complex& operator = (const Complex&);

};

class Complex;

double abs(const Complex& c);

Complex operator * (const Complex& c1, const Complex& c2);
Complex operator / (const Complex& c1, const Complex& c2);
Complex operator + (const Complex& c1, const Complex& c2);
Complex operator - (const Complex& c1, const Complex& c2);

bool operator == (const Complex& c1, const Complex& c2);
bool operator != (const Complex& c1, const Complex& c2);

std::istream& operator >> (std::istream& in, Complex& c);
std::ostream& operator << (std::ostream& out, const Complex& c);

Complex operator ""_i(long double arg);
Complex operator ""_i(unsigned long long arg);

#endif

并不是会员还是非会员。 您在成员函数中返回了引用,因为它们实际上修改了this值。

考虑以下代码:

Complex c1, c2, c3;
// ...
(c3 *= c2) += c1;

在这里将计算c3 *= c2 ,然后将结果与c1作为参数调用operator+= 如果您返回一个副本而不是c3 *= c2的引用,则下一个应用的operator+=将修改此返回的副本,而不是c3 ,这不是期望的。

请注意,您也可以将其他运算符声明为成员函数,只是为了表明引用vs复制与成员vs非成员无关:

class Complex {

    // ...

    Complex& operator *= (const Complex&);
    Complex& operator += (const Complex&);
    Complex& operator /= (const Complex&);
    Complex& operator -= (const Complex&);
    Complex& operator = (const Complex&);

    Complex operator * (const Complex& c2);
    Complex operator / (const Complex& c2);
    Complex operator + (const Complex& c2);
    Complex operator - (const Complex& c2);

};

致电运营商时,您必须查看对结果的期望。

例如,如果您使用运算符*,则可能会希望

//Some Complex instances c1 and c2 already created
Complex c3 = c1 * c2;

您不希望修改c1或c2。 所以这里的副本很好。

但是,如果您使用运算符* =,则期望结果会修改在其上调用了运算符的Complex实例。 因此,这里引用比较好,因为您将避免使用复制构造函数和析构函数。

因此,您给出的示例是可以的。

就像我上面提到的那样,重要的问题不是这是成员还是非成员,而是返回的值是否是新实例。

任何更改对象本身的操作(例如++,+ =,-=,...)都应返回对该对象的引用。 另一方面,任何导致另一个对象的操作(如二进制+,-等)都必须创建一个新对象,因为绝不能更改原始操作数。

此外,您可以让某些二进制运算符成为成员(例如,complex + int),而其他二进制运算符必须在类外部定义(例如,int + complex)。 当然,您希望这两个操作具有相同的行为。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM