复杂表达式中的重载+问题

时间:2014-12-24 01:41:21

标签: c++ operator-overloading operators

我有一个代表3D矢量的类。它有一些成员函数(点积,交叉积等)以及一些重载运算符(+ - * /)。我在复杂的表达式中使用这些运算符时遇到了麻烦。

在简化的测试用例中,如果我将运算符重载为

testclass operator+ (testclass& a, testclass& b) {
    return testclass(a.get()+b.get());
}

我能做到

testclass a = testclass(3);
testclass b = testclass(4);
testclass c = a + b;

没有问题,但是更复杂的表达

testclass c = a + b + a + b;

将无法编译。我可以通过将重载函数更改为

来解决此问题
testclass operator+ (testclass a, testclass b) {
    return testclass(a.get()+b.get());
}

然而,这涉及传递值,我理解这比第一种情况下的参考传递方案慢。我在一个数学密集型代码中使用这个类,而我的真正的类包含三个long double作为数据成员,所以我怀疑性能影响可能很大。

我的问题是:

  • 为什么会出现这种情况?
  • 我可以避免它而不诉诸价值吗?
  • 当我有三个长双打作为数据成员时,通过值而不是通过引用会影响性能吗?优化编译器(g ++ -O3)会优化它吗?

提前全部谢谢。

确切的编译错误是:

operator_overload.cpp: In function ‘int main()’:
operator_overload.cpp:37:29: error: no match for ‘operator+’ (operand types are ‘testclass’ and ‘testclass’)
         testclass c = a + b + a + b;
                             ^
operator_overload.cpp:37:29: note: candidate is:
operator_overload.cpp:30:15: note: testclass operator+(testclass&, testclass&)
     testclass operator+ (testclass& a, testclass& b) {
           ^
operator_overload.cpp:30:15: note:   no known conversion for argument 1 from ‘testclass’ to ‘testclass&’

我的完整测试代码如下:

#include <iostream>

class testclass {
public:
    testclass();
    testclass(int);
    int get();
    void set(int);
private:
    int data;
};

testclass::testclass() {
    data = 0;
}

testclass::testclass(int a) {
    data = a;
}

int testclass::get() {
    return data;
}

void testclass::set(int a) {
    data = a;
    return;
}

testclass operator+ (testclass& a, testclass& b) {
    return testclass(a.get()+b.get());
}

int main () {
    testclass a = testclass(3);
    testclass b = testclass(4);
    testclass c = a + b + a + b;
    std::cout << c.get() << std::endl;
    return 0;
}

2 个答案:

答案 0 :(得分:3)

问题是rvalues不能绑定到左值引用。 a + b + a + b的中间结果,比如a+b,是临时的,完整的表达式无效。 OTOH,const引用可以绑定到rvalues。将签名更改为testclass operator+ (const testclass& a, const testclass& b)以解决此问题。

要使上述签名有意义,您还需要testclass::get成为const方法。

答案 1 :(得分:1)

你必须使用const限定符来保持refs到rvalue

你编码:

#include <iostream>

class testclass {
public:
    testclass();
    testclass(int);
    int get() const;
    void set(int);
private:
    int data;
};

testclass::testclass() {
    data = 0;
}

testclass::testclass(int a) {
    data = a;
}

int testclass::get() const {
    return data;
}

void testclass::set(int a){
    data = a;
    return;
}

testclass operator+ (const testclass& a, const testclass& b) {
    return testclass(a.get()+b.get());
}

int main () {
    testclass a = testclass(3);
    testclass b = testclass(4);
    testclass c = a + b + a + b;
    std::cout << c.get() << std::endl;
    return 0;
}

适合我,gcc 4.9.2