为什么Visual Studio会在这里调用析构函数,但GCC不会?

时间:2015-07-15 18:16:25

标签: c++ visual-studio-2010 gcc

在Win7上运行的Visual C ++ 2010 Express中的Win32控制台项目,64位。

#include "stdafx.h"
#include <conio.h>

class Num
{
private:
    int value;
public:
    friend Num operator+(Num, Num);

    // Constructor
    Num(int i)
    {
        printf("buidling %p\n", this);
        this->value = i;
    }
    // Deconstructor
    ~Num()
    {
        printf("destroying %p\n", this);
    }
    // Getter for value
    int getVal()
    {
        return value;
    }
};

// Overload "+" operator
Num operator+(Num i, Num j)
{
    printf("in operator+\n");
    return (i.value + j.value);
}

int _tmain(int argc, _TCHAR* argv[])
{
    Num a = Num(42) + 17;
    printf("done %p %d\n", &a, a.getVal());

    // Hold up
    printf("Press any key to continue...\n");
    _getch();
    return 0;
}

当我在VC ++中观察构造过程时,Num(17)的对象被创建,然后是Num(42)的对象,然后是Num a。到目前为止都很好。在破坏时,在破坏临时的17和42个物体之前有第4个物体被破坏,最后是a。 printf显示这与重载的运算符+有关。似乎VC ++创建了一个额外的临时Num对象而没有使用构造函数,然后它复制到a并调用析构函数。相比之下,似乎GCC创建了这个副本,然后分配给该内存而不是创建此副本。

两个问题:

  1. 我是否正确地解释了VC ++在这里做了什么?为什么使用析构函数,而不是构造函数?
  2. 为什么他们的处理方式不同?似乎GCC的方法会更有效,因为它会创建/销毁更少的对象。 VC ++方法有什么好处?

1 个答案:

答案 0 :(得分:2)

您没有在Num 复制构造函数中输出任何内容,您需要添加:

Num(const Num &i)
{
    printf("buidling %p\n", this);
    this->value = i.value;
}

您的operator+()实施正在按值输入Num个对象 ,因此正在制作副本。更改operator+()以通过const参考获取对象,以避免这种情况:

Num operator+(const Num &i, const Num &j)

最后,考虑将operator+()作为Num的成员而不是独立功能实施:

class Num
{
private:
    int value;
public:
    //...

    // Getter for value
    int getVal() const
    {
        return value;
    }

    // Overload "+" operator
    Num operator+(const Num &j) const
    {
        printf("in operator+\n");
        return (value + j.getVal());
    }
};

或者:

class Num
{
private:
    int value;
public:
    //...

    // Getter for value
    int getVal() const
    {
        return value;
    }

    // Overload "+=" operator
    Num& operator+=(const Num &j)
    {
        printf("in operator+=\n");
        value += j.getVal();
        return *this;
    }

    // Overload "+" operator
    Num operator+(const Num &j) const
    {
        printf("in operator+\n");
        Num tmp(*this);
        tmp += j;
        return tmp;
    }
};