c++ - 为什么 Visual Studio 会在这里调用析构函数,而 GCC 不会?

标签 c++ visual-studio-2010 gcc

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

#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 表明这与重载的 operator+ 有关。看起来 VC++ 创建了 1 个额外的临时 Num 对象而不使用构造函数,然后将其复制到 a 并调用析构函数。相比之下,GCC 似乎创建了这个拷贝,然后将 a 分配给该内存,而不是创建这个拷贝。

两个问题:

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

最佳答案

您没有在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;
    }
};

关于c++ - 为什么 Visual Studio 会在这里调用析构函数,而 GCC 不会?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31438084/

相关文章:

c++ - 在 MFC 组合框中设置文本而不将其添加到列表中

gcc - assembly 中的位测试 (BT)

c# - 为什么新创建的 EF 实体在尝试保存时抛出 ID is null 异常?

visual-studio-2010 - 如何让 Visual Studio 将我的 MVC3 代码验证为 HTML5 而不是 XHTML 1.0 Transitional?

c# - 如何在 VS2010 中的调试 session 期间抛出异常

c - 未定义对 `shm_open' 的引用,即使在使用 -pthread -lrt 进行编译时也是如此

c - ubuntu 18.04 上的 c 文件中对 "readline"的 undefined reference (已安装 libreadline-dev,与 "-lreadline"链接

c# - 如何在 C# 中编码(marshal) C++ 枚举

c++ - 错误 : expected unqualified-id before 'for' . 编译因 -Wfatal-errors 而终止

c++ - boost::ptr_vector 上的多索引