当作为参数传递的对象超出范围时,析构函数是否会调用自身?

时间:2013-12-29 19:05:00

标签: c++ reference destructor operator-keyword

我使用静态变量来跟踪对象的实例数。我使用以下代码获得了一些不可预测的行为:

#include <iostream>
using namespace std;

class comp{
private:
 int a;
 int b;

 public:
  friend comp &operator+(comp, comp);
   static int c;
   comp(int, int);
   comp();
   ~comp();
   int getA();
   int getB();
   void print() const;
};

int comp::c = 0;

comp::~comp() {

    c--;
    cout << "destroying comp of " << a << ", " << b << ", count after decrement is  " << c << endl;
    }


comp &operator+(comp A, comp B){
  comp C = comp(A.a + B.a, A.b + B.b);
  cout << "in +, count is " << comp::c << endl;
  return C;
}

comp::comp(int A, int B){
  a = A;
  b = B;
  c++;
}

comp::comp(){
  a = 0; b = 0; c++;
}

int comp::getA(){
  return a;
}

int comp::getB(){
  return b;
}

void comp::print() const{
  cout << a << ", " << b << endl;
}

int main()
{
    cout << comp::c << endl;
    comp A = comp(3,4);
    cout << comp::c << endl;
    comp B = comp(4,5);
    cout << comp::c << endl;
    A + B;
    A.print();
    B.print();
    cout << "About to exit main, c is: " << comp::c << endl;
    return 0;
}

输出是这样的:

0
1
2
in +, count is 3
destroying comp of 7, 9, count after decrement is  2
destroying comp of 3, 4, count after decrement is  1
destroying comp of 4, 5, count after decrement is  0
3, 4
4, 5
About to exit main, c is: 0
destroying comp of 4, 5, count after decrement is  -1
destroying comp of 3, 4, count after decrement is  -2

此行为是由行

引起的
 A + B;

我最好的猜测是,当对象作为参数传递给函数时,构造函数没有被调用(因此c没有递增),但是当函数超出范围时,析构函数被称为。这导致计数的净损失。

但是,重载的运算符+通过引用传递变量。这不会阻止参数超出范围并调用析构函数吗?

无论重载的+运算符是否声明为:

,输出都是相同的
friend comp &operator+(comp, comp);

friend comp operator+(comp, comp);

这让我很困惑为什么以及如何调用析构函数。

最后一个问题:在使用重载运算符时,通过引用而不是按值传递是一种好习惯吗?如果是这样,为什么?

谢谢!

编辑: 看起来我好像混淆了语法。我以为

friend comp &operator+(comp, comp);

通过引用传递参数而不是

friend comp operator+(comp&, comp&);

请原谅我的犹豫不决的问题,但有人可以解释一下“&amp;”运算符在函数名之前执行?如果我理解正确,“&amp;”是引用运算符,给出给定变量的地址。但是,如果想要返回引用,则“*”运算符是合适的。例如:

int *a()

上述函数签名返回指向int的内存地址。

int &a()

该功能签名会返回什么?

2 个答案:

答案 0 :(得分:4)

您不会考虑默认情况下创建的对象,编译器生成的复制构造函数。定义一个,计算在那里创建的对象,数学就可以计算出来。

答案 1 :(得分:1)

您的问题是,当您将对象作为参数时,您可以复制它们。这就是那个将在范围结束时被破坏的副本。 为了避免这种情况,您应该通过引用传递它们:

comp operator+(comp& a, comp& b);

返回类型中的&是返回值,即代码中的C。这很糟糕,因为您发送了一个对本地创建的变量的引用,该变量将在范围的末尾被销毁。