在 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 分配给该内存,而不是创建这个拷贝。
两个问题:
- 我是否正确地解释了 VC++ 在这里所做的事情?为什么用析构函数,不用构造函数?
- 为什么他们的处理方式不同?看起来 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/