2015-12-30 58 views
3

我总是被告知将一个临时实例传递给引用函数是不安全的,我对以下问题感到困惑,请你们为我解释一下。我应该在operator =中使用pass-by-const-reference吗?

#include <iostream> 
using namespace std; 
int cnt = 0; 
class Complex 
{ 
public: 
    //explicit 禁止double隐式转换为Complex 
    explicit Complex(double real, double imaginary = 0) 
     : real_ (real), imaginary_(imaginary) 
    { 
     id_ = cnt++; 
     cout << "complex constructed id:" << id_ << endl; 
    } 

    //也可以explicit来禁止隐式调用拷贝构造函数 
    Complex(const Complex& other): real_ (other.real_), imaginary_(other.imaginary_) 
    { 
     id_ = cnt++; 
     cout << "complex copy constructed id:" << id_ << endl; 
    } 

    ~Complex() 
    { 
     cout << "complex destructed id:" << id_ << endl; 
    } 

    Complex& operator= (const Complex& rhs) 
    { 
     cout << "complex operator=" << endl; 
     real_ = rhs.real_; 
     imaginary_ = rhs.imaginary_; 
     return *this; 
    } 

    //return-by-reference, pass-by-const-reference 
    Complex& operator+= (const Complex& other) 
    { 
     real_ += other.real_; 
     imaginary_ += other.imaginary_; 
     return *this; 
    } 

    //return-by-reference 
    Complex& operator++() 
    { 
     ++real_; 
     return *this; 
    } 

    //return-by-const-value是为了防止a++++的情况 
    const Complex operator++(int) 
    { 
     Complex temp(*this); 
    } 

    ostream& Print(ostream& os) const 
    { 
     return os << "(" << real_ << "," << imaginary_ << ")"; 
    } 

private: 
    int id_; 
    double real_; 
    double imaginary_; 

}; 

const Complex operator+ (const Complex& lhs, const Complex& rhs) 
{ 
    cout << "complex operator+ " << endl; 
    Complex ret(lhs); 
    ret += rhs; 
    return ret; 
} 

ostream& operator<< (ostream& os, const Complex& c) 
{ 
    return c.Print(os); 
} 

int main() 
{ 
    Complex a(1, 10); 
    Complex b(2, 5); 
    Complex c(3, 0); 
    b = a + c; 
    return 0; 
} 

的代码a + c将创建类复合物,其将由const引用被传递到函数operator=的一个临时的实例。在执行operator=之前是否有任何可能由a + c创建的临时实例被破坏,导致operator=函数失败? 我编译此程序gcc4.4.7,它打印此:

enter image description here

看来,临时实例是operator=后破坏。我仍然对这个结果感到困惑,不知道这是编译器优化的结果还是C++的结果。 如果有人能够启发我,我将非常感激。

回答

4

这就是C++的工作方式。引用标准:

在一个函数调用 绑定到一个基准参数的临时对象,持续直到含有 呼叫

[12.2/5.1]

所以临时全表达的完成由a + c表达式创建的类Complex的实例保证被销毁结束后operator= c所有。

+0

谢谢,这真的很有帮助。 –